Burp Suite

基本介绍

Burp Suite是一款集成化的渗透测试工具,包含了很多功能,可以帮助我们快速完成对web应用程序的渗透测试和攻击。Burp Suite是由Java语言编写,因为Java是可以跨平台的,所以Burp Suite也是跨平台的,支持windows、linux、mac。

安装pro(Mac)

1
2
3
4
5
6
7
8
9
10
11
12
## 进入burpsuite Pro.app里的Contents
cd /Applications/Burp Suite Professional.app/Contents

## 编辑vmoptions.txt 追加内容
--add-opens=java.base/java.lang=ALL-UNNAMED
--add-opens=java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED
--add-opens=java.base/jdk.internal.org.objectweb.asm.tree=ALL-UNNAMED
--add-opens=java.base/jdk.internal.org.objectweb.asm.Opcodes=ALL-UNNAMED
-javaagent:BurpLoaderKeygen.jar
-noverify

## 启动器BurpLoaderKeygen.jar移动到当前app目录
  • 双击运行BurpLoaderKeygen.jar
  • 运行`
1
"/Library/Java/JavaVirtualMachines/jdk-21.jdk/Contents/Home/bin/java" "--add-opens=java.desktop/javax.swing=ALL-UNNAMED" "--add-opens=java.base/java.lang=ALL-UNNAMED" "--add-opens=java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED" "--add-opens=java.base/jdk.internal.org.objectweb.asm.tree=ALL-UNNAMED" "--add-opens=java.base/jdk.internal.org.objectweb.asm.Opcodes=ALL-UNNAMED" "-javaagent:/Applications/BurpLoaderKeygen.jar" "-noverify" "-jar" "/Applications/Burp Suite Professional.app/Contents/Resources/app/burpsuite_pro.jar"

代理

cacert.der

功能介绍

https://t0data.gitbooks.io/burpsuite/content/chapter7.html

darkweb

网络安全

分类文章

搜索工具

黑市交易

暗网交易中心

Docker

基础

Docker的组成

  • docker client 客户端 👉 docker daemon 交互
  • docker daemon 守护进程 👉 一般在宿主主机后台运行,等待接收来自客户端的请求消息
  • docker container 容器 👉 镜像的运行实例,我们可以把镜像看成是一个个的构建块,容器根据这些构建块搭建起了一个隔离的,拥有整个包的应用程序。每一个容器都是一个标准化单元,确保了在不同机子上也能拥有一致的行为
  • docker image 镜像 👉 包含了操作系统的一张光碟,它是一个模板文件,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)
  • 数据卷 👉 Docker 对数据持久化的解决方案,数据不会随着容器结束而丢失,通过将宿主机的某一文件目录载到容器里来实现 volumes:
  • 网络
    • bridge 模式 👉 Docker 在主机上会创建一个docker0的网桥
    • host 模式 👉 在建一个容器时,一般会为容器分配一个独立的 Network Namespace 以进行网络隔离。如果我们使用了 Host 模式,则不再分配 Network Namespace,而是和宿主机共用一个 Network Namespace。此时容器将不再拥有自己的虚拟网卡、IP 和端口,而是和宿主机共用一个 IP 和端口
    • none 模式 👉 使用 none 模式的容器拥有属于自己的 Network Namespace,但不做任何网络配置。它和宿主机以及其他容器是不互通的。如果需要和外部通信,则需要自定义网络驱动程序,自己添加网卡、配置 IP 等

Docker底层技术

  • Namespaces(资源隔离):将系统的全局资源通过抽象划分,使得在同一 namespace 中的进程看起来拥有自己的全局资源。主要有 Mount namespaces(文件系统挂载)、Network namespaces(网络)、User namespaces(用户)等的资源隔离。
  • CGroups(资源限制):对系统资源的限制,比如 CPU、内存等。
  • UnionFS(联合文件系统):一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。便于镜像的分层继承。

Docker网络

1
2
3
4
5
docker network prune

docker network rm XXX

docker network list

Docker与传统虚拟机的区别

特性 Docker 容器 传统虚拟机 (VM)
启动速度 秒级启动 (轻量级) 分钟级启动 (启动完整操作系统)
资源占用 共享主机内核,资源占用小 每个虚拟机包含完整操作系统,占用大
架构 基于容器引擎 (如 Docker Engine) 基于 Hypervisor (如 VMware、VirtualBox)
运行效率 运行在主机操作系统之上,高效 需通过 Hypervisor 间接访问硬件,性能损耗较大
文件系统 分层镜像 (Layered Images),增量存储 每个虚拟机独立的磁盘文件 (如 VMDK, VDI)
隔离性 进程级隔离,共享主机内核 完全隔离,虚拟机有自己的内核
操作系统支持 仅支持与主机相同的内核 (通常是 Linux) 支持不同的操作系统 (如在 Windows 上运行 Linux)
应用场景 微服务、CI/CD、测试环境、轻量服务 需要完整操作系统的场景,如传统应用、特定依赖环境
部署方式 Dockerfile、镜像 (Image)、容器 (Container) 镜像 (ISO)、虚拟机模板、虚拟机实例
资源调度 通过编排工具 (如 Kubernetes) 实现灵活调度 通过虚拟化平台 (如 vSphere) 进行调度
迁移灵活性 容器镜像小,迁移快 虚拟机文件大,迁移相对慢

容器的copy-on-write特性,修改容器里面的内容会修改镜像

Dockerfile的整个构建镜像过程

1
2
3
docker build -t [镜像名]:tag
docker build -t 镜像名:tag -f /xx/xxx/Dockerfile # 可以使用-f参数来指定dockerfile文件

Dockerfile的基本指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
FROM # 指定基础镜像(必须为第一个指令,因为需要指定使用哪个基础镜像来构建镜像);

MAINTAINER # 设置镜像作者相关信息,如作者名字,日期,邮件,联系方式等;

COPY # 复制文件到镜像;

ADD # 复制文件到镜像(ADD与COPY的区别在于,ADD会自动解压tar、zip、tgz、xz等归档文件,而COPY不会,同时ADD指令还可以接一个url下载文件地址,一般建议使用COPY复制文件即可,文件在宿主机上是什么样子复制到镜像里面就是什么样子这样比较好);

ENV # 设置环境变量;

EXPOSE # 暴露容器进程的端口,仅仅是提示别人容器使用的哪个端口,没有过多作用;

VOLUME # 数据卷持久化,挂载一个目录;

WORKDIR # 设置工作目录,如果目录不在,则会自动创建目录;

RUN # 在容器中运行命令,RUN指令会创建新的镜像层,RUN指令经常被用于安装软件包;

CMD # 指定容器启动时默认运行哪些命令,如果有多个CMD,则只有最后一个生效,另外,CMD指令可以被docker run之后的参数替换;

ENTRYOINT # 指定容器启动时运行哪些命令,如果有多个ENTRYOINT,则只有最后一个生效,另外,如果Dockerfile中同时存在CMD和ENTRYOINT,那么CMD或docker run之后的参数将被当做参数传递给ENTRYOINT;

进入容器命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
### 容器生命周期管理
# 搜索镜像
docker search centos
# 查看镜像层级关系
docker images --tree

# 查看容器状态
docker ps -a # 列出所有容器 (包含停止状态)
docker ps # 仅列出运行中的容器
docker inspect my_nginx # 查看容器详细信息
docker logs my_nginx # 查看容器日志输出

# 创建并运行容器
docker run -d --name my_nginx -p 8080:80 nginx

### 启动、停止、重启容器
docker start my_nginx # 启动已存在但停止的容器
docker start $(docker ps -aq) # 启动所有容器
docker stop my_nginx # 停止正在运行的容器
docker restart my_nginx # 重启容器 (相当于 stop + start)

# 立即强制停止容器
docker kill my_nginx

### 删除容器
docker rm my_nginx # 删除的容器
docker rm -f my_nginx # 强制删除运行中的容器 (相当于 kill + rm)
docker rm $(docker ps -q -f status=exited) # 删除所有已退出的容器
docker rm $(docker ps -a -q) # 删除所有已停止的容器

# 删除所有正在运行和已停止的容器
docker stop $(docker ps -a -q)
docker rm $(docker ps -a -q)

docker rm $(docker ps -aq) # 删除所有容器 (小心使用)
docker rmi $(docker images -q) # 删除所有镜像

### Docker 资源清理
docker container prune # 删除所有退出状态的容器
docker image prune # 删除 dangling 或所有未被使用的镜像
docker network prune # 删除所有未使用的网络
docker volume prune # 删除未被使用的数据卷
docker system prune # 删除已停止的容器、dangling 镜像、未被容器引用的 network 和构建过程中的 cache,安全起见,这个命令默认不会删除那些未被任何容器引用的数据卷,如果需要同时删除这些数据卷,你需要显式的指定 --volumns 参数
docker system prune --all --force --volumns # 这次不仅会删除数据卷,而且连确认的过程都没有了!注意,使用 --all 参数后会删除所有未被引用

# 暂停与恢复容器
docker pause my_nginx # 暂停容器中的所有进程
docker unpause my_nginx # 恢复被暂停的容器

### 进入容器
# attach 命令是attach到容器启动命令的终端
docker attach my_nginx

# exec 是另外在容器里面启动一个TTY终端
docker exec -it my_nginx /bin/bash

# 也可以执行单次命令,而不进入交互模式
docker exec my_nginx ls /usr/share/nginx/html

### 文件传输
docker cp [本地文件路径] [ID全称]:[容器路径]
# 或者
docker cp [ID全称]:[容器文件路径] [本地路径]

### 后台运行docker
docker run -d

导出导入镜像

export\import 与 save\load 的区别:

  • export\import 导出的镜像文件大小要小于 save\load 导出的镜像

  • export\import 是根据容器拿到的镜像,再导入时会丢失镜像所有的历史,所以无法进行回滚操作;而 save\load 的镜像,没有丢失镜像的历史,可以回滚到之前的层。

核心原因是 export 是针对容器的导出,所以只有所有层组合的最终版本;而 save 则是针对镜像的,所以可以看到每一层的信息。

1
2
3
4
5
6
7
8
### 导出导入镜像
# export\import 导入导出
docker export web > /home/docker_web.tar
docker import /home/docker_web.tar

# save\load 导入导出
docker save 9610cfc68e8d > /home/docker_web.tar
docker load < /home/docker_web.tar
修改正在运行的容器端口映射
  1. 停止容器
  2. 停止 docker 服务(systemctl stop docker)
  3. 修改这个容器的 hostconfig.json 文件中的端口(原帖有人提到,如果 config.v2.json 里面也记录了端口,也要修改)
1
2
3
4
5
6
7
8
9
10
11
12
cd /var/lib/docker/3b6ef264a040* 	# 这里是 CONTAINER ID

vi hostconfig.json

# 如果之前没有端口映射, 应该有这样的一段:
"PortBindings":{}

# 增加一个映射, 这样写:
"PortBindings":{"3306/tcp":[{"HostIp":"","HostPort":"3307"}]}

# 前一个数字是容器端口, 后一个是宿主机端口
# 而修改现有端口映射更简单, 把端口号改掉就行
  1. 启动docker服务(systemctl start docker)
  2. 启动容器

docker-compose

  • 192网段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
version: '3'
services:
app:
network_mode: bridge
IP: 192.168.1.100
ports:
- "8080:8080"
depends_on:
- db

networks:
my-network:
driver: bridge
ipam:
config:
- subnet: 192.168.1.0/24

$ docker-compose up --net=my-network

Dockerfile 更新/重构

1
docker-compose up -d --build php84

docker外部调用

1
docker run --rm -v $(pwd):/app/backend -w /app/backend dnmp-php82 composer dump-autoload

命令作用

dnmp-php82 容器中运行 composer dump-autoload,并将当前目录挂载到 /app/backend,优化 PHP 自动加载。


参数解析

参数 作用
docker run 启动一个新的 Docker 容器
--rm 容器执行完成后自动删除(不会保留实例)
-v $(pwd):/app/backend 挂载当前目录 到容器 /app/backend,让容器能访问本地代码
-w /app/backend 设置工作目录,让 composer dump-autoload/app/backend 目录执行
dnmp-php82 Docker 镜像名称,用于运行 PHP 和 Composer
composer dump-autoload 重新生成 Composer 自动加载文件,提高 PHP 代码加载效率

Docker容器时间与宿主机不一致

方法一:初始化容器时,容器时间与宿主机同步,docker run 添加时间参数

1
docker  run -itd --privileged=true -v /etc/localtime:/etc/localtime:ro

方法二:Dockerfile解决方案

1
2
3
4
5
6
7
8
9
10
11
# 方法1
# 添加时区环境变量,亚洲,上海
ENV TimeZone=Asia/Shanghai
# 使用软连接,并且将时区配置覆盖/etc/timezone
RUN ln -snf /usr/share/zoneinfo/$TimeZone /etc/localtime && echo $TimeZone > /etc/timezone

# 方法2
# CentOS
RUN echo "Asia/shanghai" > /etc/timezone
# Ubuntu
RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

方法三:docker-compose解决方案

1
2
3
4
5
6
7
8
9
10
11
12
13
#第一种方式(推荐):
environment:
TZ: Asia/Shanghai

#第二种方式:
environment:
SET_CONTAINER_TIMEZONE=true
CONTAINER_TIMEZONE=Asia/Shanghai

#第三种方式:
volumes:
- /etc/timezone:/etc/timezone
- /etc/localtime:/etc/localtime

方法四:正在运行的容器,可以宿主机直接执行命令给某个容器同步时间

1
2
3
4
5
6
#方法1  直接在宿主机操作
docker cp /etc/localtime 【容器ID或者NAME】:/etc/localtime
docker cp -L /usr/share/zoneinfo/Asia/Shanghai 【容器ID或者NAME】:/etc/localtime

#方法2 登录容器同步时区timezone,一般是因为时区不同导致时间差
ln -sf /usr/share/zoneinfo/Asia/Singapore /etc/localtime

Docker逃逸

  • 容器镜像存在的风险

  • 活动中的容器存在的风险

    • 不安全的容器应用

    • 不受限制的资源共享

    • 不安全的配置与挂载

      如果为容器设定了不安全的配置,会导致容器本身的隔离机制失效,容器的两大隔离机制如下:

      • Linux 命名空间(NameSpace):实现文件系统、网络、进程、主机名等方面的隔离
      • Linux 控制组(cgroups):实现 CPU、内存、硬盘等方面的隔离

      如果设定了以下配置就会导致相应的隔离机制失效:

      • –privileged:使容器内的 root 权限和宿主机上的 root 权限一致,权限隔离被打破
      • –net=host:使容器与宿主机处于同一网络命名空间,网络隔离被打破
      • –pid=host:使容器与宿主机处于同一进程命令空间,进程隔离被打破
      • –volume /:/host:宿主机根目录被挂载到容器内部,文件系统隔离被打破
  • 容器管理程序接口的风险

    Docker 守护进程主要监听 UNIX socket 和 TCP socket,默认情况下,Docker 只会监听 UNIX socket

    • UNIX socket
      UNIX socket 的风险主要在于 Docker 守护进程默认以宿主机的 root 权限运行,因此就可以借助这点进行提权或者容器逃逸。
      这类风险主要有两个利用场景:

      普通用户被加到 Docker 用户组内
      如果普通用户被加入到 Docker 用户组内,那么普通用户也将有权限访问 Docker UNIX socket,如果攻击者获得了这个普通用户权限,就可以借助 Docker 提权到 root 用户权限。

      具体的做法可以简单描述为:使用普通用户创建一个 privileged 为 true 的容器,在该容器内挂载宿主机硬盘并写入定时任务,然后将宿主机的 root 权限反弹回来,后期将详细介绍这种方法的使用。

      UNIX socket 挂载到容器内部
      有时为了实现容器内部管理容器,可能会将 Docker UNIX socket 挂载到容器内部,那么如果该容器被入侵,RT 就可以借助这个 socket 进行容器逃逸获得宿主机 root 权限。

    • TCP socket
      现在 Docker 守护进程默认不会监听 TCP socket,不过有时可能用户会因为方便开启 TCP socket 的监听,一般默认监听端口是 2375

      默认情况下,Docker 守护进程 TCP socket 是无加密无认证的,因此如果发现宿主机 Docker 开放了 TCP socket,就可以直接使用 docker -H 接管目标的容器

docker 逃逸

Freebuf文章

网络安全

未读

Compound Finance V2 安全审计手册

Linux kernel 堆溢出利用方法(二)

Linux应急响应思路和技巧(三):网络分析篇

卫星

夜莺监控

咖啡打印机

GhostGPT h4cker

最佳黑客纪录片推荐:网络安全迷的必备片单

分类文章

笔记 安全

freqtrade

freqtrade量化-文档

docker-compose 安装到本地

添加 config.json 和 SampleStrategy.py 两个文件

1
2
--config /freqtrade/user_data/config.json
--strategy SampleStrategy

如果启动没有反应 就重写配置

1
2
# 创建配置 - 需要回答交互式问题
docker compose run --rm freqtrade new-config --config user_data/config.json

策略定制

  • 指标
  • 入场策略规则
  • 出场策略规则
  • 推荐的最小投资回报率
  • 强烈推荐使用止损

XGBoost 训练模型

流程

步骤 内容 目的
第 1 步 安装 Freqtrade 环境 把系统搭好,能运行
第 2 步 下载币种历史数据 模拟交易所数据做训练和回测
第 3 步 写策略文件(含指标) 把逻辑/模型写进去
第 4 步 做回测 / 回测优化 看策略是否赚钱、找最佳参数
第 5 步 训练模型 + 联动策略 用 AI 做预测生成信号
1
2
3
4
5
6
## 📦 第 1 步:下载 BTC 历史数据
# 下载 5 分钟K线,过去30天
freqtrade download-data --exchange binance --pairs BTC/USDT --timeframe 5m --days 30



Git

Git本地有四个工作区域:工作目录(Working Directory)、暂存区(Stage/Index)、资源库(Repository或Git Directory)、git仓库(Remote Directory)。文件在这四个区域之间的转换关系如下:

开发 Dev

远程分支基础操作

分支配置 config

  • vim .git/config
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = XXXXX ## url修改
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "feat-2.23"]
remote = origin
merge = refs/heads/feat-2.23
vscode-merge-base = origin/master
[pull]
rebase = false
[user]
email = linyanbbb@cc.cc
[branch "master"]
remote = origin
merge = refs/heads/master
vscode-merge-base = origin/master

提交的用户名

  • 修改全局用户名(影响所有项目)
1
2
git config --global user.name "NewUsername"
git config --global user.email "newemail@example.com"
  • 仅修改当前项目的用户名
1
2
git config --local user.name "NewUsername"
git config --local user.email "newemail@example.com"

基础操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
## 原有分支进行切换地址
git remote set-url origin [url]

## 删除git信息
$ rm -rf .git/

## 追踪分支
git branch -vv

## 远程拉去分支
git fetch origin [Branch]

## 下载tag指定分支
git clone --branch [tags标签] [url]
# 或者
git clone -b [tags标签] [url]

## 删除远程分支
git push origin --delete remoteBranchName

本地分支基础操作

基础操作

1
2
3
4
5
6
7
8
9
10
11
12
13
## 查看本地分支
git branch -l

## 查看log
git log

## 切分支
git checkout -b [Branch]

## 删除本地分支
git branch -d [Branch]


开发代码冲突措施

撤销add文件并保留

1
2
3
4
# 撤销所有的已经 add 的文件:
git reset HEAD .
# 撤销某个文件或文件夹:
git reset HEAD [filename]

代码污染回退

1
2
3
4
5
## log
git log

## 强制回退版本
git reset --hard XXXXXX

开发分支遇到开发总分支更新代码

1
2
3
4
5
6
7
8
9
10
11
## 保存改动
git stash

## 查看所有stash
git stash list

## 强制更新状态
git pull --rebase origin dev-cody

## 恢复最新stash
git stash pop

分支开发中线上代码更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
## 保存改动
git stash

## 查看所有stash
git stash list

## 恢复最新stash
git stash pop

## 恢复特定stash 恢复第一个stash
git stash apply stash@{0}

## 清空
git stash clear

## 删除特定stash 恢复第一个stash
git stash drop stash@{2}

服务器必备CI CD

  • 配置
1
git config --global user.name "Your Name" git config --global user.email "your.email@example.com"

持续集成(CI)

采用 CI 意味着频繁集成较小的更改,而不是低频次地一次集成大量更新。将测试、合并和签入共享代码仓库更改的工作流程自动化,意味着团队能够以更快的速度交付更简洁的代码。更简洁的代码意味着更快的验证、更简洁的发布,以及更容易扩展的更高效的开发流程。

持续交付/部署(CD)

持续部署 (CD) 是使用自动化发布和部署软件更新的做法。 作为典型 CD 过程的一部分,代码在部署之前会自动构建并测试。

分支在开发中的更新状态

1
2
3
4
5
git config pull.rebase false

git config pull.rebase true

git config pull.ff only

Github action CI CD 服务器

工作流

  1. 在 GitHub 上的存储库中,创建 .github/workflows 目录中名为 deploy.yml 的工作流文件。

  2. deploy.yml 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
name: Deploy Demo

on: # 工作流程触发
push: # 触发事件
branches:
- main # 或你使用的默认分支名称
pull_request: # 也在 PR 事件触发时运行
schedule:
- cron: '0 0 * * *' # 每天 00:00 运行

jobs:
build:
runs-on: ubuntu-latest # 运行环境
steps:
- name: Checkout code
uses: actions/checkout@v4 # 拉取代码

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 18 # 安装 Node.js 18

- name: Install dependencies
run: npm install # 安装依赖

- name: Run tests
run: npm test # 运行测试

- name: Deploy
if: success() # 仅在上一步成功时执行
run: echo "Deploying to production..."
  1. SSH连接目标服务器完成CI/CD

公钥放入secrets里面

Golang 面试题

基础

锁系列

进程、线程、Goroutine(协程)区别

  • 进程 - 直观点说,保存在硬盘上的程序运行之后,会在内存空间里形成一个独立的内存体,这个内存体有自己独立的地址空间,有自己的堆,上级挂靠单位是操作系统。
  • 线程 - 轻量级进程(LightWeight Process,LWP),是操作系统调度(CPU调度)执行的最小单位。
  • 协程 - 比线程更轻量级的存在,协程完全由程序控制

make和new区别

  • make和new都是golang用来分配内存的內建函数,且在堆上分配内存,make 即分配内存,也初始化内存。new只是将内存清零,并没有初始化内存。
  • make返回的还是引用类型本身;而new返回的是指向类型的指针。
  • make只能用来分配及初始化类型为slice,map,channel的数据;new可以分配任意类型的数据。

数组和切片区别

  • 数组是一个长度固定的数据类型,其长度在定义时就已经确定,内存空间大小是固定;切片是一个长度可变的数据类型,内存空间运行时动态分配,其长度在定义时可以为空,也可以指定一个初始长度 append追加切片
  • 当数组作为函数参数时,函数操作的是数组的一个副本,不会影响原始数组;当切片作为函数参数时,函数操作的是切片的引用,会影响原始切片

GMP协程调度器

内核线程-thread(Machine),协程(Goroutine),处理器-G的上下文环境(Processor)

  • G:goroutine协程,基于协程建立的用户态线程
  • M:machine,它直接关联一个os内核线程,用于执行G
  • P:processor处理器,P里面一般会存当前goroutine运行的上下文环境(函数指针,堆栈地址及地址边界),P会对自己管理的goroutine队列做一些调度

调度器策略

  • 全局G队列 - 通过go func()来创建一个goroutine,有两个存储G的队列,一个是局部调度器P的本地队列、一个是全局G队列。新创建的G会先保存在P的本地队列中,如果P的本地队列已经满了就会保存在全局的队列中
  • 复用线程 - work stealing机制hand off机制(偷别人的去执行,和自己扔掉执行),G只能运行在M中,一个M必须持有一个P,M与P是1:1的关系,

work stealing机制如果P的本地队列为空,就会想其他的MP组合偷取一个可执行的G来执行
hand off机制当本线程因为G进行系统调用阻塞时,线程释放绑定的P,把P转移给其他空闲的线程执行,此时M1如果长时间阻塞,可能会执行睡眠或销毁

  • 利用并行 - 我们可以使用GOMAXPROCS设置P的数量,这样的话最多有GOMAXPROCS个线程分布在多个CPU上同时运行。GOMAXPROCS也限制了并发的程度,比如GOMAXPROCS = 核数/2,则最多利用了一半的CPU核进行并行
  • 抢占策略 - 1对1模型的调度器,需要等待一个co-routine主动释放后才能轮到下一个进行使用, 如果一个goroutine使用10ms还没执行完,CPU资源就会被其他goroutine所抢占

调度器的生命周期

在了解调度器生命周期之前,我们需要了解两个新的角色M0和G0

M0(跟进程数量绑定,一比一):

  • 启动程序后编号为0的主线程
  • 在全局变量runtime.m0中,不需要在heap上分配
  • 负责执行初始化操作和启动第一个G
  • 启动第一个G之后,M0就和其他的M一样了

G0(每个M都会有一个G0):

  • 每次启动一个M,都会第一个创建的gourtine,就是G0
  • G0仅用于负责调度G
  • G0不指向任何可执行的函数
  • 每个M都会有一个自己的G0
  • 在调度或系统调用时会使用M切换到G0,再通过G0进行调度

M0和G0都是放在全局空间的

并发 sync

sync.waitgroup, sync.map ,sync.Lock, sync.RWLock,sync.Pool….

通道 - channel

每个通道都有一个锁和一个读写队列,当多个协程同时向通道写入数据或者从通道读取数据时,只有一个协程能够获取到锁进行读写操作,其他协程则会被阻塞直到获得锁

1
2
3
4
5
6
7
8
9
// 发送方
go func() {
ch <- 1
}()
// 接收方
go func() {
num := <-ch
fmt.Println(num)
}()

channel 死锁的场景和原因浅析
锁死场景

  • 没有缓冲区的时候,单协程内通道同时写和读
  • 无缓冲区的时候,通道输入数据早于接收方的协程开启
  • 没有数据的channel里拿数据引起的死锁

解决方案

  • 做缓冲通道 -》 缓冲通道可以用cap()测试出来
  • 解决多值发送死锁 循环接收

互斥锁 Mutex 与 读写锁 RWMutex 区别

  • Mutex只允许一个goroutine同时获得锁,适用于需要频繁修改共享资源的场景;
  • RWMutex允许多个goroutine同时获得读锁,但只允许一个goroutine获得写锁,适用于需要频繁读取共享资源的场景

并发Map - sync.Map

线程池 - sync.Pool

sync.Pool 其实就是一个线程安全的对象池,用于保存和复用临时对象,,在大批量申请和释放相同类型的临时对象时使用 sync.Pool 可以减少很多内存分配和回收操作,减小GC压力。

内存

CG

微服务之间通信方式 rpc Grpc http

go.work

多模块 - 项目结构

1
2
3
4
5
6
7
8
/workspace
├── go.work
├── service1/
│ ├── go.mod
│ ├── main.go
├── service2/
│ ├── go.mod
│ ├── main.go

你的 go.work 文件可能是:

1
2
3
4
5
6
go 1.21

use (
./service1
./service2
)

Go 1.18 及以上版本引入的 工作区模式(Workspace Mode) 的配置文件

而无需使用 replace 指令或 GOPATH

go.work 是 Go 1.18+ 的新功能,用于 管理多个 Go 模块。
它让 多个本地模块 互相引用,避免 go.mod 里写 replace。
go work use 命令可以方便地添加模块

数学基础

线性代数

向量

二维向量

三维向量

向量计算

向量-加法

向量缩放-相乘

基向量

基向量

基向量(Basis Vector)是构成向量空间的最小单位,就像拼积木的“基本零件”。

基向量1

我们有一个向量:


📌 线性变换后的基向量

变换后的基向量为:

  • Transformed
  • Transformed

🔄 用变换后的基向量表示原向量

将原向量用变换后的基向量表示:

代入具体值:


🧭 几何解释

  • 绿色箭头:表示变换后的
  • 红色箭头:表示变换后的
  • 黄色箭头:表示变换后的
  • 网格线展示了整个坐标系统的变换效果

图中还包含了中文注释:

  • “变换后的 i”
  • “变换后的 j”

张成

🧭 线性变换与基向量的映射

向量缩放-相乘

在线性变换下可表示为:

矩阵

🧮 2×2矩阵与线性变换

向量缩放-相乘

这类变换可以写成矩阵与向量的乘法形式:

该过程表示向量 在新的变换基底(列向量)上的线性组合。


📊 图像说明

  • 左侧图展示了标准基 在变换后的位置,形成变换坐标系。
  • 黄色向量是线性组合后的新向量。
  • 中文翻译“2×2矩阵”强调了基础的线性代数结构。

2x2矩阵

复合矩阵

复合矩阵

复合矩阵1

矩阵乘法

矩阵乘法

三维矩阵

三维矩阵

三维矩阵1

行列式

行列式是一个从方阵计算出来的实数或复数,用来衡量该矩阵的“体积变换能力”和是否“可逆”。

设二阶矩阵:

它的行列式为:

行列式

线性方程组

线性方程组

逆矩阵

列空间

不同维度之间的转换

二维转三维

二维转三维

2 = 输入空间有两个基向量
3 = 三行代表有三个独立坐标来描述

三维转二维

三维转二维

3 = 输入空间有三个基向量
2 = 两行代表有三两个独立坐标来描述

一维

一维

点积

定义:
对于两个向量

  • 反映了两个向量方向上的相似性
  • :同向
  • :垂直
  • :反向
  • 可以用来计算投影、夹角、长度平方

点积

点积1

点积2

对偶性

对称性Ux

对称性Uy

向量投影到数轴

二维投影到数轴

二维投影到数轴1

叉积 仅适用于三维向量

定义:

对于 ,叉积结果是一个向量:

方向确定正负

方向

定向

定向

定向1

叉积

叉积1

叉积2

叉积3

线性变换

线性变换

线性变换1

必然与V和W垂直 长度与这两个向量张成的平行四边形面积相同

线性变换2

范数

范数(Norm)是数学中用来**衡量向量“有多大”**的工具,也就是向量的“长度”或“大小”的一种通用定义方式。

1. 向量的范数

任意一组向量设为 如下:

  • 向量的1范数: 向量的各个元素的绝对值之和
  • 向量的2范数: 向量的每个元素的平方和再开平方根
  • 向量的负无穷范数: 向量所有元素的绝对值中最小的
  • 向量的正无穷范数: 向量所有元素的绝对值中最大的
  • 向量的p范数: 向量元素绝对值的p次方和,然后再开P次方根

2. 矩阵的范数

对于矩阵 , 举例而说:

1
2
3
4
A = [
-1, 2, 3;
4, -6, 6;
]
  • 矩阵的1范数(列范数):矩阵的每一列上的元素绝对值先求和,再从中取个最大值
  • 矩阵的2范数: 矩阵 的最大特征值开平方根

特征值分解,特征向量

  • 特征值分解可以得到特征值与特征向量
  • 特征值表示的是这个特征到底有多重要,而特征向量表示这个特征是什么

矩阵A 的特征值与其特征向量, 特征值 满足:

特征值分解是将一个矩阵分解为如下形式:

: 一个对角矩阵,每一个对角元素是一个特征值里面的特征值是由大到小排列的,这些特征值所对应的特征向量就是描述这个矩阵变化方向(从主要的变化到次要的变化排列)。 特征值分解表示矩阵的信息可以由其特征值和特征向量表示。

条件概率

联合概率与边缘概率

  • 联合概率:联合概率指类似于这样,包含多个条件,且所有条件同时成立的概率。

  • 边缘概率:边缘概率指类似于这样,仅与单个随机变量有关的概率。

  • 区别:联合概率是指在多元的概率分布中多个随机变量分别满足各自条件的概率。而边缘概率是某个事件发生的概率,而与其它事件无关。

  • 联系: 联合分布可求边缘分布,但若只知道边缘分布,无法求得联合分布。

独立性与条件独立性

8.

  • 独立性:
  • 条件独立: 再条件Z发生时, X, Y 条件独立:

期望,方差,协方差,相关系数

1. 期望

**如果相互独立,则。 **

2. 方差

如果相互独立,

3. 协方差

协方差是衡量两个遍历的总体误差。

独立变量的协方差为0。

4. 相关系数

值越接近1,说明两个变量正相关性(线性)越强。越接近-1,说明负相关性越强,当为0时,表示两个变量没有相关性


QA

1. 矩阵正定性

  • 问题:矩阵正定性的判断?

    • 矩阵中的特征值均不小于 0 , 则为半正定。
    • 矩阵中的特征值都大于 0, 则为正定。
  • Hessian矩阵正定性在梯度下降中的应用

    • 在判断优化算法的可行性时Hessian矩阵的正定性起到了很大的作用,若Hessian正定,则函数的二阶偏导恒大于0,函数的变化率处于递增状态,在牛顿法等梯度下降的方法中,Hessian矩阵的正定性可以很容易的判断函数是否可收敛到局部或全局最优解。

信息论

  • 基本思想: 一件不太可能的事情发生, 要比一件非常可能的事情发生提供更多的信息
  • 性质:
    • 非常可能发生的事情信息量较少,并且极端情况下,一定能够发生的事件应该没有信息量
    • 比较不可能发生的事件具有更大的信息量
    • 独立事件应具有增量的信息。例如,投掷的硬币两次正面朝上传递的信息量,应该是投掷一次硬币正面朝上的信息量的两倍。

信息论 Self-Information

自信息衡量一个特定事件发生所带来的信息量,定义如下:

  • 事件 ( x ) 发生的概率较大时,信息量较小(可预测)。
  • 事件 ( x ) 发生的概率较小时,信息量较大(意外)。
  • 单位:比特(bit),如果以对数底为 2;若使用自然对数,则单位为 nat。

示例

  • 一个 6 面骰子掷出 “1” 的概率为 ,则:

    说明掷出 “1” 这个结果提供了约 2.585 比特的信息量。

信息熵 Entropy

信息熵衡量整个概率分布的不确定性或平均信息量,定义为:

  • 熵高:当所有事件的概率相等(如均匀分布),不确定性最大。
  • 熵低:当某个事件的概率接近 1,而其他事件几乎不可能发生时,熵接近 0,表示信息几乎是确定的。

示例

  • 公平骰子的熵:

    说明掷一次骰子,平均每次获得 2.585 比特的信息量。

  • 非公平骰子(某些面概率较大):

    因为有些结果更确定,熵变小了。

互信息 Mutual Information MI

互信息衡量两个随机变量 之间的 信息共享量,即知道一个变量后,能减少多少对另一个变量的不确定性。定义为:

或等价地:

  • 完全独立 时,,说明它们互不影响。
  • 完全相关 时, 最大,说明一个变量完全确定了另一个变量。

示例

  • 在一个通信系统中,发送的消息 与接收的消息 之间的互信息反映了多少信息被成功传输,而没有丢失或引入噪声。

相对熵 KL散度

相对熵(Kullback-Leibler Divergence, KL 散度) 用于衡量两个概率分布 之间的 差异,表示在使用分布 代替真实分布 时,信息丢失的程度

定义

KL 散度的数学公式:

或者对于连续分布:

其中:

  • 是 **真实分布**(ground truth)
  • 是 **近似分布**(模型预测分布)
  • 衡量了在 处, 之间的差异

KL 散度的含义:
  • 如果 ,则 KL 散度为 0,即两个分布完全一致时,信息损失为 0。
  • 如果 ,则 KL 散度为正数,即 不能完美地表示 ,产生信息损失。

示例

假设真实分布 和近似分布 如下:

计算 KL 散度:

交叉熵 Cross Entropy

交叉熵 是衡量两个分布之间相似性的度量,用于计算模型预测的分布 和真实分布 之间的匹配程度。

定义

交叉熵的数学公式:

或者对于连续分布:


交叉熵的含义:

  • 交叉熵衡量的是使用 预测 的平均编码长度
  • 在机器学习中,交叉熵通常作为分类问题的损失函数,用于优化模型,使得预测概率 接近真实分布

KL 散度与交叉熵的关系

交叉熵与 KL 散度有如下关系:

其中:

  • 是 **熵(Entropy)**,表示分布 自身的不确定性,与 无关。
  • 表示由于使用 代替 产生的额外信息损失。

📌 结论

  • 交叉熵 真实分布 的自身熵 加上 KL 散度 组成。
  • 最小化交叉熵等价于最小化 KL 散度,因为 是固定的。

示例

如果

  • 真实分布的熵(Entropy)
  • 交叉熵(Cross Entropy)
  • KL 散度(Relative Entropy)

联合熵 Joint Entropy

定义

联合熵 衡量两个随机变量 同时出现 时的不确定性。

对于离散随机变量 ,联合熵的数学公式为:

其中:

  • 是联合概率分布,表示事件 共同发生的概率。

对于连续随机变量:


直观理解:

  • 联合熵衡量的是 的整体不确定性。
  • 如果 独立,则:
  • 如果 相关,则: 这表明 之间的关系减少了不确定性。

示例:

假设 分别表示投掷两颗骰子的结果:

  • 如果骰子是公平的且独立的,则:
  • 如果骰子其中一颗的结果依赖于另一颗(例如总和固定为7),则:

条件熵 Conditional Entropy

定义

条件熵 表示在已知随机变量 的情况下, 仍然存在的不确定性,即 相对于 的信息熵。

数学定义:

或者对于连续变量:

其中:

  • 是条件概率,表示在给定 的情况下, 的概率。
直观理解:
  • 条件熵衡量的是 的剩余不确定性,假设 已知。
  • 如果 完全独立,那么:
  • 如果 完全由 决定,则:
示例:

假设 是 “天气”(晴天/下雨), 是 “带伞”(是/否):

  • 如果天气完全决定是否带伞(晴天不带,雨天带),则
  • 如果有些人无论天气如何都随机决定是否带伞,则 会大于 0。

关系:联合熵、条件熵、信息熵

联合熵、条件熵和信息熵之间的关系:

或者:


直观理解:
  • 联合熵 组成的整个系统的不确定性。
  • 条件熵 是在知道 之后, 还剩下的不确定性。
  • 信息熵 自身的不确定性。

在机器学习与信息论中的应用

概念 定义 应用
信息熵 衡量单个变量的不确定性 数据压缩、特征选择
联合熵 衡量 组成的系统的不确定性 多变量建模
条件熵 在已知 的情况下, 的剩余不确定性 机器学习中的分类问题

📌 实际应用:

  • 特征选择 中,条件熵 可以衡量一个特征 对目标变量 的贡献。
  • 机器学习 中,决策树 使用 信息增益 来选择最优特征。
  • 数据压缩(如 Huffman 编码) 中,利用 联合熵和条件熵 进行高效编码。

在机器学习中的应用

  • 交叉熵用于分类问题的损失函数
    • 二分类问题(如逻辑回归、二元交叉熵)中:
    • 多分类问题(如 Softmax 交叉熵)中:
  • KL 散度用于概率分布匹配
    • 变分自编码器(VAE)GAN 训练中用于衡量两个概率分布的相似度。
    • 强化学习(RL) 中,KL 散度用于策略更新。

🚀 总结

概念 公式 作用
自信息 衡量单个事件的意外程度
信息熵 衡量整个分布的不确定性
互信息 衡量两个变量之间的相关性
KL 散度 衡量 近似 的信息损失
交叉熵 衡量 的编码效率
KL 散度与交叉熵关系 最小化交叉熵等价于最小化 KL 散度
联合熵 衡量 的整体不确定性
条件熵 衡量在 已知情况下 的不确定性
联合熵与条件熵关系 联合熵 = 信息熵 + 条件熵

大数据问题

数据流采样

在一个无限的整数数据流,如何从中等概率随机抽取 k 个整数出来? – 采样问题

K = 1 时(单个元素采样)

抽样方法

  1. 当第一个整数到达时,直接保留该整数。
  2. 当第二个整数到达时,以 的概率使用该整数替换第一个整数,以 的概率丢弃该整数。
  3. 当第 个整数到达时,以 的概率使用第 个整数替换当前选中的整数,以 的概率丢弃 个整数。

归纳法验证

1. 基础情况

时,第一个数被选中的概率为 100%,成立。

2. 假设 时成立

个数中,每一个被选中的概率为

3. 证明 时仍然成立

个数被选中的概率:

个数被选中的概率:

因此,该方法保证每个数被选中的概率相同,正确性成立。

K > 1 时(多个元素采样)

抽样方法

  1. 个整数到达时,全部保留。
  2. 个整数()到达时
    • 的概率替换当前选中的 个整数中的某一个。
    • 的概率丢弃当前整数。

归纳法验证

1. 基础情况

时,所有数都被选中,概率为 100%,成立。

2. 假设 时成立

即前 个数中,每个数被选中的概率为:

3. 证明 时仍然成立
  • 个数被选中的概率:
  • 个数被选中的概率:

因此,该方法保证了每个数被选中的概率相同,正确性成立。

基数统计

计算一个数据流中不同元素的个数?

  1. HashSet
    采用 hashet,不断加入, 最终的hashset大小就是所求答案。 缺点: 单机内存存不下

  2. bitmap
    前提: 假设已经知道不同元素的个数的上限,假设为 N
    我们可以建立一个长度为N的 bit 数组, 每个元素与 bit 数组的某一位一一对应, 该位为1,则表示此元素在集合中,为 0 表示不再集合中,最终的答案为 bitmap 中1的个数。
    缺点: bitmap 与实际情况下不同元素的个数无关,而与不同元素的个数上限有关。

  3. Linear Counting
    基本思路:

  • 选择一个哈希函数 h, 其结果服从均匀分布
  • 开一个长度为 m 的bitmap,初始化为 0
  • 数据流每来一个元素,计算哈希值并对m取模,然后将该位置置1
  • 最后,若 bitmap 中还有 u 个bit 为 0, 则不同元素的总数近似为 m的选择
    对于 bitmap 长度的选择,主要由两个因素决定:基数大小以及容许的误差。 假设基数大小大约为n, 允许误差大约为 , 则 m 需要满足如下约束:
  1. Loglog Counting
    基本思路:
  • 均匀随机化。 选择哈希函数 h 的几大条件:
  • h 应该尽可能减少冲突
  • h 的结果是几乎服从均匀分布的。
    哈希后的结果是固定长度的。
    对于每个元素,计算出哈希值,每个哈希值是等长的,长度为 L
  1. HyperLogLog Counting

频率估计

计算数据流中任意元素的出现的次数

  1. HashMap
    用 HashMap 来记录每个元素出现的次数。
    缺点: 占用内存大,单机内存无法存下这个巨大的 HashMap

  2. 数据分片 + HashMap
    假设有 n 台机器, 那么每台机器都有一个HashMap, 第 i 台处理 hash(elem) % n == i-1 的元素。
    查询时, 先计算元素在哪台机器上,然后去那台机器上的HashMap读取。

  3. Count-Min Sketch

  • 选定 d 个哈希函数, 并建立一个 d * m 的二维整数数组作为哈希表
  • 对于每个元素,分别使用 d 个hash 函数计算相应哈希值,并对 m 取余,然后在对应的位置上增1,二维数组中的每个整数称为 sketch。
  • 对于要查询的元素,取出 d 个sketch, 返回最小的哪一个。(d 个sketch 都是该元素的近似频率,返回任意一个均可)
    优点: 省内存;
    缺点:对于出现次数较少的元素,准确性很差。主要是由于 hash 冲突比较严重
  1. Count-Mean-Min Sketch
    对 Count-Min Sketch 做了改进。
  • 来了一个查询,按照 Count-Min Sketch 的正常流程,取出它的d个sketch
  • 对于每个hash函数,估算一个噪音 = 该行所有整数(除了被查询的这个元素)的平均值
  • 真正的sketch = 该行的sketch - 该行的噪音
  • 返回 d 个sketch 的中位数

Heavy Hitters

寻找数据流中出现最频繁的 k 个元素?

  1. HashMap + Heap
    用一个 HashMap存放所有元素出现的次数,用一个小根堆,容量为k,存放目前出现过的最频繁的 k 个元素:
  • 元素过来时,更新 HashMap, 并且在堆中查找该元素,如果找到,则+1并调整堆; 如果没有找到,则将该元素次数与堆顶元素比较,如果大于,则把堆顶元素替换为该元素,并调整堆。
  • 时间复杂度为, 空间复杂度为
  1. 多机 HashMap + Heap
    将数据分片, 第 i 台机器只处理 的元素
    每台机器都有一个 HashMap 和 Heap, 格子计算出 top k 元素
    将每台机器的 Heap, 通过网络汇总到一台机器上,并将多个Heap合成一个 Heap
  2. Count-Min Sketch + Heap
  3. Lossy Counting
  4. SpaceSaving

范围查询

给定一个无限的整数数据流,如何查询在某个范围内的元素出现的总次数?

  1. Array of Count-Min Sketches

成员查询 Bloom Filter

给定一个无限的数据流和一个有限集合,如何判断数据流中的元素是否在这个集合中?

布隆过滤器本质上是二进制向量 + 一系列随机映射函数, 主要用于检测某元素是否在一个集合中。

  • 优点: 空间效率和查询时间都远远超过一般的算法

布隆过滤器原理

  • 加入元素:当一个元素被加入到集合时,通过 K 个哈希函数将这个元素映射成一个位数组中的K个点,把它们置为1。
  • 检索元素:查看对应的 K 个点是否都为1 : 如果存在任意一个为 0, 被检元素一定不在; 如果都为1,则很可能存在。

布隆过滤器与Bitmap 区别

布隆过滤器使用了 k 个哈希函数,每个元素对应 k 个bit,从而降低了冲突的概率

布隆过滤器缺点

  • 存在误判:即可能要查找的元素不在容器内,但 k 个位置上都是 1
  • 删除困难:一旦删除元素,不能简单将对应 k 个位置置为 0

布隆过滤器实现

假设要存的数据量为n, 期望的误判率为 fpp,我们需要计算 Bit 数组的大小 m, hash 函数的个数 k,并选择合适的哈希函数。

  • Bit 数组大小选择:

  • 哈希函数选择:

抽样方法

分层抽样的适用范围?

分层抽样利用事先掌握的信息, 充分考虑了保持样本结构和总体结构的一致性,当总体由差异明显的几部分组成的时候,适合用分层抽样。

概率分布

分布名称 分布公式 期望 方差
伯努利分布
二项分布

伯努利分布

  • 伯努利试验: 随机试验,每次试验都只有两个结果 0 与 1, 则称为伯努利试验。

假设存在一个的观测值的数据集,假设每次观测都是独立从分布中抽取,那么可以构造关于的似然函数:

如果采用极大似然的方式来估计的值,那么,对应的极大似然函数为:

关于的导数等于 0,就得到极大似然的估计值:

二项分布

  • n重伯努利试验: 将伯努利试验独立重复进行 n 次, 称为 n 重伯努利试验。

  • n 重伯努利试验中成功的总次数 X 服从二项分布:

Beta 分布

概率论

1. 事件运算规律

  • 交换律:

  • 结合律:

  • 分配律:

2. 条件概率

3. 事件独立性

  • A,B 相互独立的充要条件为 A 与 与 B 或 相互独立。
  • 当 0 < P(A) < 1 时, A, B 相互独立 等价于 P(B|A) = P(B) 或 成立
  • n 个事件间相互独立 –> 这n个事件必两两独立; 反之不成立。

4. 五大公式

  • 加法公式:

  • 减法公式:

  • 乘法公式:

  • 全概率公式:

  • 贝叶斯公式:

5. 古典型概率

  • 定义: 在样本空间中,有有限 n 个样本点,且每个样本点的发生具有相等的可能性,则称这种有限等可能试验为古典概型。

  • 如果事件 A 由 个样本点组成,则事件 A 的概率为:

6. 几何型概率

  • 定义:当试验的样本空间是某区域(该区域可以是一维,二维或三维等), 以 表示当前样本空间 的几何度量(长度,面积,体积)等。 为有限,且试验结果出现在 中的任意区域的可能性只与该区域几何度量成正比。

  • 如果事件 A 的样本点表示的区域为 , 那么事件A的概率为:

7. n重伯努利试验

  • 伯努利试验: 随机试验,每次试验都只有两个结果 , 则称为伯努利试验。
  • n重伯努利试验: 将伯努利试验独立重复进行 n 次, 称为 n 重伯努利试验。

若每次实验中, , 那么 n 重伯努利试验中事件 A 发生 k 次的概率为:

随机变量与分布

1.离散型随机变量

2. 连续型随机变量

3. 常见分布

  • **几何分布:**n重伯努利试验中, 在第 k 次试验时才首次试验成功的概率服从几何分布。

  • 超几何分布: N 件商品中含有 M 件次品,从中任意一次取出 n 件(或从中一件接一件不放回的取n件), 令 X = 抽取的n件商品中的次品件数, 则 X 服从参数为 n, N, M 的超几何分布。

  • **泊松分布:**一段时间内电话总机接到的呼叫次数, 候车的旅客数,保险索赔的次数都服从泊松分布。

  • **均匀分布:**X 在区间 [a,b] 上服从均匀分布,则

  • 指数分布:

  • 正态分布

随机变量的数学特征

1. 数学期望

  • 离散型随机变量:

  • 连续型随机变量:

  • 性质:设 C 为常数, X, Y 为随机变量

    • 的充要条件为 **X , Y不相关。**
  • 随机变量X的函数 的数学期望:

    • X 为离散随机变量:

    • X 为连续随机变量:

  • 随机变量 (X, Y) 的函数 的数学期望:

    • (X, Y) 为离散随机变量:

    • (X,Y) 为连续随机变量:

2. 方差

  • , 但不能从反推出 C 为常数
  • 的充要条件是 X 与 Y 不相关。

3. 常见分布期望与方差

https://blog.csdn.net/Ga4ra/article/details/78935537

  • 0-1 分布:

  • 二项分布:

4. 协方差

  • 定义: 对于随机变量X ,Y , 如果 存在,则称之为 X 和 Y 的协方差:

  • 性质:

5. 相关系数

  • 定义: 对于随机变量 X 和 Y, 如果 , 则称 为 X 与 Y 的相关系数。

  • 性质:

    使

6. 独立与不相关

  • 不相关: 如果随机变量 X 与 Y 的相关系数 , 则称 X 与 Y 不相关。

  • 相互独立一定不相关,不相关不一定相互独立。

  • 对于二维正态随机变量(X,Y), X 和 Y相互独立的充要条件为

  • 对于二维正态随机变量(X,Y), X,Y相互独立与不相关等价。

知识点

1. 古典概率模型

  • 原理: 在一个样本空间 S 中, 若 S 中每个样本点发生的可能性相同,那么事件A 发生的概率 。(有限等可能试验)

  • 例子: 一个骰子掷到 1 的概率:

2. 几何概率

  • 原理: 在一个几何形状 S 中随机抽取一个点,求该点属于子形状 T 的概率。(延伸到几何度量上的有限等可能试验)

  • 例子: 在一个边长为 2 的正方形内抽取一个点, 求该点属于其内切单位圆的概率。

3. 数学期望

  • 原理:一个离散随机变量X的数学期望为

  • 举例:以1/2 的概率取1, 以 1/2 的概率取 0,则此时的期望为

4. 贝叶斯

  • 条件概率:

贝叶斯定理

1. 基本概率

  • :边缘概率
  • :联合概率
  • :条件概率

2. 两大规则

  • 加和规则(sum rule):

  • 乘积规则(product rule):

  • 贝叶斯定理:

3. 实例说明

QA

1. 简单古典概率

有n个不同的球,每次抽取1个球:

  • 有放回的抽取,抽取 m 个排成一列,求不同排列总数。
  • 无放回的抽取,抽取 m 个排成一列,求不同排列总数。
  • 无放回的抽取,抽取m个忽视次序的组成一组,求不停组合总数。
  • 将所有球分为 k 个不同的组,忽视每一组中元素的次序,且每组恰好有 个球 , 求不同分组结果数。

2. 纸牌问题

  • 问题:54 张牌,分成 6 份, 每份 9 张牌, 大小王在一起的概率?(阿里一面)

  • 答案:

    • 分母: 总样本空间为将54张牌放入 1-54 的方法总数:
    • 分子: 大小王属于 1-9 的方法总数为 , 因此大小王在一起的方法总数为
    • 概率为:

3. 棍子问题

  • 问题:一根棍子折三段能组成三角形的概率?

  • 解答:

    • 假设:棍子长度为1,第一段长度为, 第二段长度为 , 第三段长度

    • 分母:总样本空间为: 1 * 1 = 1

    • 分子:两边之和大于第三边

化简画图最终得到子空间面积为

4. 采样问题

  • 问题:从 1,2,…, n 中有放回的均匀采样 m次,问出现过的不同数字的个数 x 的期望为多少?

出现的不同数字的个数 X 可以表示为 , 其中 表示 i 是否出现,如果出现, 为1,否则为 0

i 没有在 m 次采样中出现过的概率为: ,那么,有:

那么期望可加:

5. 贝叶斯

  • 问题:某城市发生一起汽车撞人逃跑事件,该城市只有两种颜色的车,蓝20%绿80%, 事发时现场只有一个目击者,他指正是蓝车,但根据专家分析,当时那种条件下能看正确的可能性是80%,那么肇事的车是蓝车的概率是多少?

假设事件 A 为目击者指正蓝车, 事件B为肇事车为蓝车,事件C为肇事车为绿车,那么有:

6. 假期期望

  • 问题:某公司有这么一个规定: 只要有1个员工过生日,当天所有员工全部放假一天。但在其余时候,所有员工都没有假期,必须正常上班。这个公司需要雇佣多少员工,才能让公司一年内所有员工的总工作期望值最大?

假设有 n 名员工, X表示不放假的天数,则总工作时间为 nX; 假设第 i 天不放假则 , 第 i 天放假则 , 那么则有:

时关于 n 增加, 时,关于n减少。

7. 下雨概率

  • 问题:你有三位好友,他们都在西雅图工作,西雅图是出了名的爱下雨,每天下雨的概率高达 2/3。 假设你的好心能够以 1/3 的概率正确判断是否在下雨。 加入他们中恰好有两位告诉你今天西雅图在下雨,问实际上下雨的概率是多少?

8. 见面概率

9. 为何推荐使用高斯分布?

当我们由于缺乏关于某个实数上分布的先验知识而不知道该选择怎样的形式时,正态分布是默认的比较好的选择,其中有两个原因:

  1. 我们想要建模的很多分布的真实情况是比较接近正态分布的。

    中心极限定理说明很多独立随机变量的和近似服从正态分布。这意味着在实际中,很多复杂系统都可以被成功地建模成正态分布的噪声,即使系统可以被分解成一些更结构化的部分。

  2. 第二,在具有相同方差的所有可能的概率分布中,正态分布在实数上具有最大的不确定性。因此,我们可以认为正态分布是对模型加入的先验知识量最少的分布。

10. 玫瑰花

  • 问题:一个活动,n个女生手里拿着长短不一的玫瑰花,无序的排成一排,一个男生从头走到尾,试图拿更长的玫瑰花,一旦拿了一朵就不能再拿其他的,错过了就不能回头,问最好的策略及其概率?

11. 切比雪夫不等式

切比雪夫不等式 描述了这样一个事实,事件大多会集中在平均值附近。

12. 0~1均匀分布的随机器如何变化成均值为0,方差为1的随机器

[0, 1] 均匀分布的随机器的均值为 1/2, 方差为 1/12., 那么变换为:

13. 红蓝球

  • 问题:抽蓝球红球,蓝结束红放回继续,平均结束游戏抽取次数

设抽到 蓝球 的概率为 , 设抽到红球的概率为 , 那么抽取到的次数为:

那么就有:

我们令:

那么有:

那么我们就可以得到:

当 n 趋向于无穷大时次数等于:

高斯分布

高等数学

欧拉公式

机器学习

机器学习

机器学习的基本思路

  1. 把现实生活中的问题抽象成数学模型,并且很清楚模型中不同参数的作用
  2. 利用数学方法对这个数学模型进行求解,从而解决现实生活中的问题
  3. 评估这个数学模型,是否真正的解决了现实生活中的问题,解决的如何?

原理

  1. 上面提到的认字的卡片在机器学习中叫——训练集
  2. 上面提到的“一条横线,两条横线”这种区分不同汉字的属性叫——特征
  3. 小朋友不断学习的过程叫——建模
  4. 学会了识字后总结出来的规律叫——模型

分成三类 监督学习、无监督学习、强化学习

监督学习

监督学习是指我们给算法一个数据集,并且给定正确答案。机器通过数据来学习正确答案的计算方法

我们准备了一大堆猫和狗的照片,我们想让机器学会如何识别猫和狗。当我们使用监督学习的时候,我们需要给这些照片打上标签。

我们给照片打的标签就是“正确答案”,机器通过大量学习,就可以学会在新照片中认出猫和狗。

这种通过大量人工打标签来帮助机器学习的方式就是监督学习。这种学习方式效果非常好,但是成本也非常高。

非监督学习

无监督学习的任务是从给定的数据集中,挖掘出潜在的结构。

我们把一堆猫和狗的照片给机器,不给这些照片打任何标签,但是我们希望机器能够将这些照片分分类。

通过学习,机器会把这些照片分为2类,一类都是猫的照片,一类都是狗的照片。虽然跟上面的监督学习看上去结果差不多,但是有着本质的差别:

非监督学习中,虽然照片分为了猫和狗,但是机器并不知道哪个是猫,哪个是狗。对于机器来说,相当于分成了 A、B 两类。

强化学习

强化学习更接近生物学习的本质,因此有望获得更高的智能。它关注的是智能体如何在环境中采取一系列行为,从而获得最大的累积回报。通过强化学习,一个智能体应该知道在什么状态下应该采取什么行为。

判别模型、生成模型

1. 判别模型

  • 代表:K 近邻、感知机(神经网络)、决策树、逻辑斯蒂回归、最大熵模型、SVM、提升方法、条件随机场
  • 思想: 由数据直接学习决策函数 条件概率分布 作为预测的模型。
  • 理解: 直观的说,判别模型学习的是类别之间的最优分隔面,反映的是不同类数据之间的差异
  • 举例:要确定一个羊是山羊还是绵羊,用判别模型的方法是从历史数据中学习到模型,然后通过提取这只羊的特征来预测出这只羊是山羊的概率,是绵羊的概率。

2. 生成模型

  • 代表:朴素贝叶斯、隐马尔可夫模型、混合高斯模型、贝叶斯网络、马尔可夫随机场

  • 思想:由数据学习得到联合概率密度分布 , 然后求出条件概率分布 作为预测的模型:

  • 举例:利用生成模型是根据山羊的特征首先学习出一个山羊的模型,然后根据绵羊的特征学习出一个绵羊的模型,然后从这只羊中提取特征,放到山羊模型中看概率多少,放到绵羊模型中看概率多少,哪个大就是哪个。

3. 判别模型 vs 生成模型

  • 由生成模型能够得到判别模型,但由判别模型得不到生成模型

  • 当存在“隐变量”时,只能使用生成模型

隐变量:当我们找不到引起某一现象的原因时,就把这个在起作用,但无法确定的因素,叫“隐变量”

  • 判别方法的特点:

    • 缺点:不能反映训练数据本身的特性。
    • 优点:它寻找不同类别之间的最优分类面,反映的是异类数据之间的差异。
    • 优点:直接面对预测,往往学习的准确率更高。
    • 优点:由于直接学习P(Y|X)或P(X),可以对数据进行各种程度上的抽象、定义特征并使用特征,因此可以简化学习问题。
  • 生成方法的特点:

    • 优点: 可以从统计的角度表示数据的分布情况,能够反映同类数据本身的相似度。但它不关心到底划分各类的那个分类边界在哪。
    • 优点:生成方法的学习收敛速度更快,即当样本容量增加的时候,学到的模型可以更快的收敛于真实模型。
    • 优点:当存在隐变量时,仍可以用生成方法学习。此时判别方法就不能用。
    • 缺点:学习和计算过程比较复杂

4. 判别模型、生成模型与监督/无监督学习的关系总结

模型类别 监督学习 无监督学习
判别模型 常见,如 SVM、CNN 罕见
生成模型 朴素贝叶斯等 常见,如 GAN、VAE、GMM

QA

1. 生成模型和判别模型基本形式,有哪些?

  • 生成模型: 朴素贝叶斯、HMM、混合高斯模型、马尔科夫随机场
  • 判别模型: LR,SVM,神经网络,CRF,Boosting

距离度量方法

机器学习实操的7个步骤

  1. 收集数据
  2. 数据准备
  3. 选择一个模型
  4. 训练
  5. 评估
  6. 参数调整
  7. 预测(开始使用)

案例目标:区分红酒和啤酒

步骤1:收集数据

颜色 酒精度 种类
610 5 啤酒
599 13 红酒
693 14 红酒

步骤2:数据准备

我们将数据分成3个部分:训练集(60%)、验证集(20%)、测试集(20%),用于后面的验证和评估工作。

步骤3:选择一个模型

研究人员和数据科学家多年来创造了许多模型。有些非常适合图像数据,有些非常适合于序列(如文本或音乐),有些用于数字数据,有些用于基于文本的数据。

在我们的例子中,由于我们只有2个特征,颜色和酒精度,我们可以使用一个小的线性模型,这是一个相当简单的模型。

  • 特征预处理、数据清洗是很关键的步骤,往往能够使得算法的效果和性能得到显著提高。

    归一化、离散化、因子化、缺失值处理、去除共线性等,数据挖掘过程中很多时间就花在它们上面。

  • 特征选择:

    筛选出显著特征、摒弃非显著特征,需要机器学习工程师反复理解业务。特征选择好了,非常简单的算法也能得出良好、稳定的结果。这需要运用特征有效性分析的相关技术,如 相关系数、卡方检验、平均互信息、条件熵、后验概率、逻辑回归权重等方法。

步骤4:训练

大部分人都认为这个是最重要的部分,其实并非如此~ 数据数量和质量、还有模型的选择比训练本身重要更多(训练知识台上的3分钟,更重要的是台下的10年功)。

这个过程就不需要人来参与的,机器独立就可以完成,整个过程就好像是在做算术题。因为机器学习的本质就是将问题转化为数学问题,然后解答数学题的过程。

步骤5:评估

一旦训练完成,就可以评估模型是否有用。这是我们之前预留的验证集和测试集发挥作用的地方。评估的指标主要有 准确率、召回率、F值。

这个过程可以让我们看到模型如何对尚未看到的数是如何做预测的。这意味着代表模型在现实世界中的表现。

  • 过拟合、欠拟合 判断是模型诊断中至关重要的一步。常见的方法如交叉验证,绘制学习曲线等。
  • 误差分析 也是机器学习至关重要的步骤。通过观察误差样本,全面分析误差产生误差的原因:是参数的问题还是算法选择的问题,是特征的问题还是数据本身的问题 ?

这个过程需要反复迭代,调优-诊断-调优

步骤6:参数调整

完成评估后,您可能希望了解是否可以以任何方式进一步改进训练。我们可以通过调整参数来做到这一点。当我们进行训练时,我们隐含地假设了一些参数,我们可以通过认为的调整这些参数让模型表现的更出色。

工程上,主要提升算法准确度的方法是分别在模型的前端(特征清洗和预处理,不同的采样模式)与后端(模型融合)上下功夫。因为他们比较标准可复制,效果比较稳定。而直接调参的工作不会很多,毕竟大量数据训练起来太慢了,而且效果难以保证。

步骤7:预测

我们上面的6个步骤都是为了这一步来服务的。这也是机器学习的价值。这个时候,当我们买来一瓶新的酒,只要告诉机器他的颜色和酒精度,他就会告诉你,这时啤酒还是红酒了。

机器学习脑图

flowchart LR
    A[机器学习模型]
    
    A --> B[有监督模型]
    B --> B1[单模型]
    B1 --> B1B[线性模型]
    B1B --> B1B1[线性回归]
    B1B --> B1B2[逻辑回归]
    B1B --> B1B3[Lasso]
    B1B --> B1B4[Ridge]
    B1B --> B1B5[LDA]
    B1 --> B1C[K-NN]
    B1 --> B1D[决策树]
    B1D --> B1D1[ID3]
    B1D --> B1D2[C5.0]
    B1D --> B1D3[CART]
    B1 --> B1E[神经网络]
    B1E --> B1E1[感知机]
    B1E --> B1E2[神经网络]
    B1 --> B1F[支持向量机]
    B1F --> B1F1[线性可分]
    B1F --> B1F2[线性支持]
    B1F --> B1F3[线性不可分]
    B --> B2[集成学习]
    B2 --> B2A[Boosting]
    B2A --> B2A1[GBDT]
    B2A --> B2A2[AdaBoost]
    B2A --> B2A3[XGBoost]
    B2A --> B2A4[LightGBM]
    B2A --> B2A5[CatBoost]
    B2 --> B2B[Bagging]
    B2B --> B2B1[随机森林]

    A --> C[无监督模型]
    C --> C1[聚类]
    C1 --> C1A[k-means]
    C1 --> C1B[层次聚类]
    C1 --> C1C[谱聚类]
    C --> C2[降维]
    C2 --> C2A[PCA]
    C2 --> C2B[SVD]

    A --> D[强化学习-概率模型]
    D --> D1[EM算法]
    D --> D2[MCMC]
    D --> D3[贝叶斯]
    D3 --> D3A[朴素贝叶斯]
    D3 --> D3B[贝叶斯网络]
    D --> D4[概率图]
    D4 --> D4A[CRF]
    D4 --> D4B[HMM]
    D --> D5[最大熵模型]

QA

1. 如果给你一些数据集,你会如何分类?

根据数据类型选择不同的模型,如LR或者SVM,决策树。

  • 假如特征维数较多,可以选择SVM模型,如果样本数量较大可以选择LR模型,但是LR模型需要进行数据预处理

  • 假如缺失值较多可以选择决策树

  • 还可以在考虑正负样例比比,通过上下采样平衡正负样例比。

2. 分类算法列一些有多少种?

  • 单一分类方法: LR, SVM, 决策树, 朴素贝叶斯,神经网络, KNN
  • 集成学习算法:基于 Bagging 和 Boosting 算法思想,随机森林,GBDT,Adaboost,XGboost。

🚀监督学习 分类、回归

监督学习需要有明确的目标,很清楚自己想要什么结果。 比如:按照“既定规则”来分类、预测某个具体的值

  1. 选择一个适合目标任务的数学模型
  2. 先把一部分已知的“问题和答案”(训练集)给机器去学习
  3. 机器总结出了自己的“方法论”
  4. 人类把”新的问题”(测试集)给机器,让他去解答

监督学习的2个任务:回归、分类

  1. 分类 - 对各种事物分门别类,用于离散型
  2. 回归 - 预测连续的、具体的数值

监督学习的任务是学习一个模型,对给定的输入预测相应的输出,这个模型的一般形式维一个决策函数或一个条件概率分布

  • 决策函数:输入 X 返回 Y;其中 Y 与一个阈值比较,然后根据比较结果判定 X 的类别

  • 条件概率分布:输入 X 返回 X 属于每个类别的概率;将其中概率最大的作为 X 所属的类别

分类案例 如何预测离婚

1:构建问题,选择模型

对话能反映出夫妻之间潜在的问题,他们在对话中的争吵、欢笑、调侃和情感表露创造了某种情感关联。通过这些对话中的情绪关联可以将夫妻分为不同的类型,代表不同的离婚概率。

2:收集已知数据

3:训练出理想模型

4:对新用户进行预测

12年以来,每隔一两年,默里和戈特曼都会与参与研究的那700对夫妻交流。两个人的公式对离婚率的预测达到了94%的准确率

回归案例 芝麻信用分是怎么来的

个人信用评估方法——FICO

他跟芝麻信用类似,用来评估个人的信用状况。FICO 评分系统得出的信用分数范围在300~850分之间,分数越高,说明信用风险越小

下面我们来模拟一下 FICO 的发明过程,这个过程就是监督学习力的回归

1:构建问题,选择模型

财富总额貌似跟信用有关,因为马云不讲信用的损失是非常巨大的,所以大家从来没有听说马云会不还信用卡!而一个乞丐不讲信用的损失是很小的,这条街混不下去了换一条街继续。

2:收集已知数据

3:训练出理想模型

有了这些数据,我们通过机器学习,就能”猜测”出这5种数据和信用分数的关系。这个关系就是公式 f

测试验证的具体方法是:

  1. 将5种数据套入公式,计算出信用分
  2. 用计算出来的信用分跟这个人实际的信用分(预先准备好的)进行比较
  3. 评估公式的准确度,如果问题很大再进行调整优化

4:对新用户进行预测

当我们想知道一个新用户的信用状况时,只需要收集到他的这5种数据,套进公式 f 计算一遍就知道结果了!

主流的监督学习算法

算法 解释 类型
朴素贝叶斯 分类 贝叶斯分类法是基于贝叶斯定定理的统计学分类方法。它通过预测一个给定的元组属于一个特定类的概率,来进行分类。朴素贝叶斯分类法假定一个属性值在给定类的影响独立于其他属性的 —— 类条件独立性。
决策树 分类 决策树是一种简单但广泛使用的分类器,它通过训练数据构建决策树,对未知的数据进行分类。
SVM 分类 支持向量机把分类问题转化为寻找分类平面的问题,并通过最大化分类边界点距离分类平面的距离来实现分类。
逻辑回归 分类 逻辑回归是用于处理因变量为分类变量的回归问题,常见的是二分类或二项分布问题,也可以处理多分类问题,它实际上是属于一种分类方法。
线性回归 回归 线性回归是处理回归任务最常用的算法之一。该算法的形式十分简单,它期望使用一个超平面拟合数据集(只有两个变量的时候就是一条直线)。
回归树 回归 回归树(决策树的一种)通过将数据集重复分割为不同的分支而实现分层学习,分割的标准是最大化每一次分离的信息增益。这种分支结构让回归树很自然地学习到非线性关系。
K邻近 分类+回归 通过搜索K个最相似的实例(邻居)的整个训练集并总结那些K个实例的输出变量,对新数据点进行预测。
Adaboosting 分类+回归 Adaboost目的就是从训练数据中学习一系列的弱分类器或基本分类器,然后将这些弱分类器组合成一个强分类器。
神经网络 分类+回归 它从信息处理角度对人脑神经元网络进行抽象, 建立某种简单模型,按不同的连接方式组成不同的网络。

集成学习

https://www.jiqizhixin.com/articles/2018-07-28-3

组合多个弱监督模型以得到一个更好更全面的强监督模型,其思想在于:即便某一个弱分类器得到了错误的预测,其他的弱分类器也可以将错误纠正回来。

集成方法奏效的原因是不同的模型通常不会在测试集上产生相同的误差。集成模型能至少与它的任一成员表现得一样好。如果成员的误差是独立的,集成将显著提升模型的性能。

学习策略推荐:

  • 数据集大: 划分成多个小数据集,学习多个模型进行组合。
  • 数据集小: 利用 Bootstrap 方法进行抽样,得到多个数据集,分别训练多个模型再进行组合。

1. Bagging

代表模型: 随机森林, Bagging meta-estimator

先通过采样构造 k 个不同的数据集,学习得到k 个基学习器, 基学习器之间不存在依赖关系,可同时生成。

更具体的,如果采样所得的训练集与原始数据集大小相同,那所得数据集中大概有原始数据集 2/3 的实例

  • Bootstrap: 一种有放回的抽样方法,目的是为了得到统计量的分布以及置信空间。

    1. 采用有放回抽样方法从原始样本中抽取一定数量的样本
    2. 根据抽出的样本计算想要得到的统计量T
    3. 重复上述N次(一般大于1000),得到N个统计量T
    4. 根据这N个统计量,即可计算出统计量的置信区间
  • Bagging 的基本思路:

    1. 利用Bootstrap对训练集随机采样,重复进行 T
    2. 基于每个采样集训练一个弱学习器,得到 T 个弱学习器
    3. 预测时,分类问题采用投票方式, 回归问题采用 N 个模型预测平均方式。

2. Boosting

代表模型:AdaBoost, XGBoost, GBDT, Light GBM, CatBoost

学习一系列弱学习器,然后组合成一个强学习器。基于串行策略:弱学习器之间存在依赖关系,新的学习器需要根据上一个学习器生成。

  • Boosting基本思路:

    1. 先从初始训练集训练一个弱学习器,初始训练集各个样本权重相同

    2. 根据上一个弱学习器的表现,调整样本权重,是的分类错误的样本得到更多关注

    3. 基于调整后的样本分布,训练下一个弱学习器、

    4. 测试时,对各基学习器加权得到最终结果

3. Stacking

训练一个模型用于组合其他各个模型。首先我们先训练多个不同的模型,然后把之前训练的各个模型的输出为输入来训练一个模型,以得到一个最终的输出。

  • Stacking 基本思路:首先我们先训练多个不同的模型,然后把之前训练的各个模型的输出为输入来训练一个模型,以得到一个最终的输出。

    • 先从初始训练集训练 T不同的初级学习器;
    • 利用每个初级学习器的输出构建一个次级数据集,该数据集依然使用初始数据集的标签;
    • 根据新的数据集训练次级学习器
    • 多级学习器的构建过程类似。

QA

0. Boosting 与 Bagging 区别

  • Bagging中每个训练集互不相关,也就是每个基分类器互不相关,而Boosting中训练集要在上一轮的结果上进行调整,也使得其不能并行计算
  • Bagging中预测函数是均匀平等的,但在Boosting中预测函数是加权的

1. Boosting, Bagging 与偏差,方差

Boosting 能提升弱分类器性能的原因是降低了偏差Bagging 则是降低了方差

  • Boosting:

    • Boosting 的基本思路就是在不断减小模型的训练误差(拟合残差或者加大错类的权重),加强模型的学习能力,从而减小偏差;
    • 但 Boosting 不会显著降低方差,因为其训练过程中各基学习器是强相关的,缺少独立性。
  • Bagging:

    • n独立不相关的模型预测结果取平均,方差是原来的 1/n
    • 假设所有基分类器出错的概率是独立的,超过半数基分类器出错的概率会随着基分类器的数量增加而下降。

分类模型 逻辑回归

Logistic 回归简介

logistic回归用于解决的是分类问题,其基本思想是:根据现有数据对分类边界线建立回归公式,以此进行分类。也就是说,logistic 回归不是对所有数据点进行拟合,而是要对数据之间的分界线进行拟合。

  • 逻辑回归的本质: 极大似然估计
  • 逻辑回归的激活函数:Sigmoid
  • 逻辑回归的代价函数:交叉熵

Logistic 回归的数学表达

如何求解最优的

首先,我们依旧是要找到一个合适的损失函数,在Logistic回归中的损失函数为:

我们最终给它加一个正则化项:

最后,我们要求最优参数的话,依旧是使用梯度下降算法来获取 的最小值时对应的参数。


QA

1. 逻辑回归与线性回归

  • 逻辑回归处理分类问题,线性回归处理回归问题

  • 线性回归的拟合函数本质上是对 输出变量 y 的拟合, 而逻辑回归的拟合函数是对 label 为1的样本的概率的拟合

    线
  • 线性回归其参数计算方式为最小二乘法, 逻辑回归其参数更新方式为极大似然估计

  • 线性回归更容易受到异常值的影响, 而LR对异常值有较好的稳定性。

2. 推导一下 LR

  • sigmoid :

  • LR 的定义:

  • LR 满足伯努利分布:

  • 损失函数(极大似然): 对于训练数据集,特征数据 和其对应的分类标签 , 假设 m 个样本是相互独立的,那么极大似然函数为:

    那么它的 log 似然为:

  • 参数优化(梯度上升)

  • 损失函数:

3. LR 如何实现多分类?

  • 方式1: 修改逻辑回归的损失函数,使用softmax函数构造模型解决多分类问题,softmax分类模型会有相同于类别数的输出,输出的值为对于样本属于各个类别的概率,最后对于样本进行预测的类型为概率值最高的那个类别。
  • 方式2: 根据每个类别都建立一个二分类器,本类别的样本标签定义为0,其它分类样本标签定义为1,则有多少个类别就构造多少个逻辑回归分类器。

若所有类别之间有明显的互斥则使用softmax分类器,若所有类别不互斥有交叉的情况则构造相应类别个数的逻辑回归分类器。

4. LR 为何要对特征进行离散化

  • 非线性。 逻辑回归属于广义线性模型,表达能力受限;单变量离散化为N个后,每个变量有单独的权重,相当于为模型引入了非线性,能够提升模型表达能力,加大拟合; 离散特征的增加和减少都很容易,易于模型的快速迭代;
  • 速度快。 稀疏向量内积乘法运算速度快,计算结果方便存储,容易扩展
  • 鲁棒性。 离散化后的特征对异常数据有很强的鲁棒性:比如一个特征是年龄>30是1,否则0。如果特征没有离散化,一个异常数据“年龄300岁”会给模型造成很大的干扰;
  • 方便交叉与特征组合: 离散化后可以进行特征交叉,由M+N个变量变为M*N个变量,进一步引入非线性,提升表达能力。
  • 稳定性: 特征离散化后,模型会更稳定,比如如果对用户年龄离散化,20-30作为一个区间,不会因为一个用户年龄长了一岁就变成一个完全不同的人。当然处于区间相邻处的样本会刚好相反,所以怎么划分区间是门学问。
  • 简化模型: 特征离散化以后,起到了简化了逻辑回归模型的作用,降低了模型过拟合的风险。

5. 逻辑回归中,增大 L1 正则化会是什么结果

所有参数 w 都会变成 0。

分类模型 决策树

决策树是一个分而治之的递归过程。

  • 开始,构建根节点,将所有训练数据都放在根节点。
  • 然后,选择一个最优特征,按照这一特征将训练数据集分割成子集,使得各个子集有一个在当前条件下最好的分类。
  • 如果子集未分类完毕,则在子集中选择一个最优特征,继续进行划分,直到所有训练数据子集都被正确分类或没有合适的特征为止。
算法 划分标准
ID3 信息增益
C4.5 信息增益率
CART 基尼系数

决策树三要素

  • 特征选择: 从训练数据中众多的特征中选择一个特征作为当前节点的分裂标准,如何选择特征有着很多不同量化评估标准标准,从而衍生出不同的决策树算法。
  • 决策树生成: 根据选择的特征评估标准,从上至下递归地生成子节点,直到数据集不可分则停止决策树停止生长。
  • 决策树的修剪: 决策树容易过拟合,一般来需要剪枝,缩小树结构规模、缓解过拟合。剪枝技术有预剪枝和后剪枝两种。

1. 特征的选择

有三种方法进行特征选择:ID3: 信息增益,C4.5: 信息增益比,CART: 基尼系数

1. ID3

思想: 计算所有特征划分数据集D,得到多个特征划分数据集D的信息增益,从这些信息增益中选择最大的,因而当前结点的划分特征便是使信息增益最大的划分所使用的特征。

1
2
3
4
5
- 对当前例子集合,计算各属性的信息增益;
- 选择信息增益最大的属性Ak;
- 把在Ak处取值相同的例子归于同一子集,Ak取几个值就得几个子集;
- 对既含正例又含反例的子集,递归调用建树算法;
- 若子集仅含正例或反例,对应分枝标上P或N,返回调用处。

信息增益: 度量以 某特征划分数据集前后的信息熵的差值 。 信息熵能够表示样本集合的不确定性,因此我们能够通过前后集合信息熵的差值来衡量使用当前特征对于样本集合D划分效果的好坏。

假设划分前样本集合D的熵为 。使用某个特征A划分数据集D,计算划分后的数据子集的熵为

注意: 在决策树构建中,我们总是希望集合往最快到达纯度更高 的子集合发展,因此我们总是选择是的信息增益最大的特征来划分当前集合。

  • 缺点:信息增益对分支较多的属性有所偏好,因此有人提出采用信息增益比来划分特征。

2. C4.5

信息增益比本质: 在信息增益的基础之上乘上一个惩罚参数。特征个数较多时,惩罚参数较小;特征个数较少时,惩罚参数较大。

信息增益比对可取值数目较少的属性有所偏好。C4.5 先从候选划分属性中找出信息增益高于平均水平的属性,再从中选择信息增益比最高的。

相对于 ID3 算法的改进:用信息增益比来选择属性,克服了用信息增益选择属性偏向选择多值属性的不足

3. CART

CART 既可以用于分类,也可以用于回归。

基尼系数 表示集合 D 的不确定性,基尼系数 表示集合 D 经过 A = a 分割后的不确定性。 基尼系数越小,样本的不确定性越小。

分类问题中,假设有 K 个类,样本点属于第 k 类的概率为 , 则概率分布的基尼系数定义为

如果样本集合 根据特征 是否取一可能值 被分割成 两部分, 那么在特征 A 的条件下, 集合 D 的基尼系数定义为:

  • 从根节点开始,对节点计算现有特征的基尼系数,对于每一个特征,根据 “是” 与 “否” 划分为两个部分,根据上式计算划分过后的基尼系数。

  • 在所有可能的特征 A 以及该特征所有的可能取值aa中,选择基尼指数最小的特征及其对应的取值作为最优特征和最优切分点。然后根据最优特征和最优切分点,将本节点的数据集二分,生成两个子节点。

  • 对两个字节点递归地调用上述步骤,直至节点中的样本个数小于阈值,或者样本集的基尼指数小于阈值,或者没有更多特征后停止。

2. 剪枝处理

0. 剪枝的作用

剪枝处理是决策树学习算法用来解决过拟合的一种办法。

在决策树算法中,为了尽可能正确分类训练样本, 节点划分过程不断重复, 有时候会造成决策树分支过多,以至于将训练样本集自身特点当作泛化特点, 而导致过拟合。 因此可以采用剪枝处理来去掉一些分支来降低过拟合的风险。

1. 预剪枝

在决策树生成过程中,在每个节点划分前先估计其划分后的泛化性能, 如果不能提升,则停止划分,将当前节点标记为叶结点。

2. 后剪枝

生成决策树以后,再自下而上对非叶结点进行考察, 若将此节点标记为叶结点可以带来泛化性能提升,则修改之。

QA

1. ID3, C4.5, CART 这三种决策树的区别

  • ID3 决策树优先选择信息增益大的属性来对样本进行划分, 但是这样的划分方法有一个很大的缺点: 当一个属性可取值数目较多时, 可能在这个属性对应值下的样本只有一个或者很少个, 此时它的信息增益将很高, ID3会认为这个属性很适合划分。
  • C4.5树:不采用信息增益作为划分依据,而是采用信息增益率作为划分依据。但是仍不能完全解决以上问题,而是有所改善。
  • CART树:它使用gini系数作为节点的分裂依据。

2. 树形结构为何不需要归一化?

因为数值缩放不影响分裂点位置,对树模型的结构不造成影响。
按照特征值进行排序的,排序的顺序不变,那么所属的分支以及分裂点就不会有不同。而且,树模型是不能进行梯度下降的,因为构建树模型(回归树)寻找最优点时是通过寻找最优分裂点完成的,因此树模型是阶跃的,阶跃点是不可导的,并且求导没意义,也就不需要归一化。

3. 分类决策树与回归决策树的区别

分类模型 感知机

感知机模型

感知机可以拟合任何线性函数,这也就意味着任何线性分类线性回归问题都可以用感知器来解决。

感知器的训练

感知器的训练主要包含两大问题:

  • 如何判断一个样本是不是被正确分类?

  • 如何定义损失函数?

1. 如何判断一个点被正确分类?

误分类分为以下两种情况:

  • 时,得出 , 此时出现误分类
  • 时,得出 ,此时也出现误分类

那么,我们分析,对于误分类的数据 来说,必有:

那么,我们得出,我们可以通过 来得出一个点是不是误分类点。

2. 损失函数

感知机中采用的损失函数是误分类点到超平面S的总距离。

输入样本中的任意一点到超平面S的距离:

那么误分类点到超平面 S 的距离为:

是一个固定值,可以不用考虑,这样我们也可以得出我们的**损失函数**如下:

3. 求取w, b

损失函数对于 方向上的梯度为:

那么随便给定一个误分类点, 对w,b的更新如下:

4. 为何信息增益会偏向多取值特征?

从直观的理解上来说,当特征取值较多时, 根据此特征划分得到的子集纯度有更大的可能性会更高(对比取值较少的特征), 因此划分之后的熵会更低,而又由于划分之前的熵是一定的,因此信息增益更大。

分类模型 朴素贝叶斯

基本概念

1. 条件概率

  • 含义: 表示 y 发生的条件下 x 发生的概率。

2. 先验概率

  • 含义: 表示事件发生前的预判概率。 这个可以是基于历史数据统计,也可以由背景常识得出,也可以是主观观点得出。一般都是单独事件发生的概率,如 P(A)

3. 后验概率

  • 基于先验概率求得的反向条件概率,形式上与条件概率相同(若 P(X|Y) 为正向,则 P(Y|X) 为反向)

贝叶斯公式

贝叶斯公式如下:

  • P(Y) 叫做先验概率,意思是事件X发生之前,我们对事件Y发生的一个概率的判断
  • P(Y|X) 叫做后验概率,意思是时间X发生之后,我们对事件Y发生的一个概率的重新评估
  • P(Y,X) 叫做联合概率, 意思是事件X与事件Y同时发生的概率。

条件独立假设

朴素贝叶斯采用条件独立假设的动机在于: 简化运算。

从机器学习视角理解朴素贝叶斯

朴素贝叶斯 = 贝叶斯方法 + 条件独立假设。

在机器学习中,我们可以将 X 理解为“具有某特征”, 而 Y 理解为“类别标签”,于是有:

而贝叶斯派目的是要对 Y 进行优化:

朴素贝叶斯中的三种模型

1. 多项式模型

多项式模型适用于离散特征情况,在文本领域应用广泛, 其基本思想是:我们将重复的词语视为其出现多次

2. 高斯模型

https://blog.csdn.net/u012162613/article/details/48323777

http://www.letiantian.me/2014-10-12-three-models-of-naive-nayes/

高斯模型适合连续特征情况,我们先给出高斯公式:

3. 伯努利模型

伯努利模型适用于离散特征情况,它将重复的词语都视为只出现一次。

我们看到,”发票“出现了两次,但是我们只将其算作一次。

QA

1. 朴素贝叶斯为何朴素?

朴素贝叶斯的朴素性体现在该算法基于一个简单的假设: 所有的变量都是相互独立的,用贝叶斯公式表达如下:

而在很多情况下,所有变量几乎不可能满足两两之间的条件。

2. 朴素贝叶斯分类中某个类别的概率为0怎么办?

问题: 如下,A1,A2,A3是三个特征,Y是分类结果。

A1 A2 A3 Y
1 1 0 1
0 1 1 1
1 0 1 0
0 1 0 0
0 0 1 0
1
2
3
4
P(Y=0) = 3/5
P(Y=1) = 2/5
P(Y=0|A1=1,A2=0,A3=0) = 3/5 * 1/3 * 2/3 * 1/3 = 2/45
P(Y=1|A1=1,A2=0,A3=0) = 2/5 * 1/2 * 1/4 * 1/2 = 1/40

答案是 拉普拉斯平滑

3. 朴素贝叶斯的要求是什么?

  • 贝叶斯定理
  • 特征条件独立假设

4. 朴素贝叶斯的优缺点?

  • 优点: 对小规模数据表现很好,适合多分类任务,适合增量式训练。
  • 缺点:对输入数据的表达形式很敏感(离散、连续,值极大极小之类的)。

5. 朴素贝叶斯与 LR 区别?

  • 朴素贝叶斯是生成模型,根据已有样本进行贝叶斯估计学习出先验概率 P(Y) 和条件概率 P(X|Y),进而求出联合分布概率 P(XY),最后利用贝叶斯定理求解P(Y|X), 而LR是判别模型,根据极大化对数似然函数直接求出条件概率 P(Y|X)
  • 朴素贝叶斯是基于很强的条件独立假设(在已知分类Y的条件下,各个特征变量取值是相互独立的),而 LR 则对此没有要求
  • 朴素贝叶斯适用于数据集少的情景,而LR适用于大规模数据集。

分类模型 随机森林

  • 思想:总体样本当中随机取一部分样本进行训练,通过多次这样的结果,进行投票获取平均值作为结果输出,这就极大可能的避免了不好的样本数据,从而提高准确度。因为有些是不好的样本,相当于噪声,模型学入噪声后会使准确度不高。
  • 举例:假设有1000个样本,如果按照以前的思维,是直接把这1000个样本拿来训练,但现在不一样,先抽取800个样本来进行训练,假如噪声点是这800个样本以外的样本点,就很有效的避开了。重复以上操作,提高模型输出的平均值。

1. 原理

随机森立是 Bagging 的优化版本。其包含的思想在于: 随机选择样本数建立多个训练集并随机选取特征集合,根据多个训练集与特征集合来建立多颗决策树,然后进行投票决策。

随机森林的最终目的是建立 m 颗决策树,而每颗决策树的建立过程如下:

  • 如果训练集大小为N,对于每棵树而言,随机且有放回地从训练集中的抽取N个训练样本,作为该树的训练集。
  • 如果每个样本的特征维度为M,指定一个常数m<<M,随机地从M个特征中选取m个特征子集,每次树进行分裂时,从这m个特征中选择最优的
  • 每棵树都尽最大程度的生长,并且没有剪枝过程。

随机森林中的随性性指的是:数据采样的随机性与特征采用的随机性。 这两个随机性的引入对随机森林的分类性能直观重要,它们使得随机森林不容易陷入过拟合,且具有很好的抗噪能力。

2. 影响因素

  • 森林中任意两棵树的相关性: 相关性越大,错误率越大
  • 森林中每棵树的分类能力:每棵树的分类能力越强,整个森林的错误率越低。

3. 特征 m 的选择

m 是随机森林中唯一的一个参数。

  • 减小特征选择个数m,树的相关性和分类能力也会相应的降低
  • 增大m,两者也会随之增大。

QA

1. 随机森林的过拟合如何解决?

通过交叉验证来调整树的数量。

2. 随机怎了如何处理缺失值?

  • 首先,给缺失值预设一些估计值, 如平均数,中位数等
  • 然后,根据估计的数值,建立随机森林,把所有的数据放进随机森林里面跑一遍。记录每一组数据在决策树中一步一步分类的路径.
  • 判断哪组数据和缺失数据路径最相似,引入一个相似度矩阵,来记录数据之间的相似度,比如有N组数据,相似度矩阵大小就是N*N
  • 如果缺失值是类别变量,通过权重投票得到新估计值,如果是数值型变量,通过加权平均得到新的估计值,如此迭代,直到得到稳定的估计值。

3. 什么是 OOB?

OOB 即 out-of-bag , 又称袋外数据。 这是由于 Bagging 方法会采用 Boostrap 进行抽样, 每次约有 的样本不会出现在抽样后的样本集合中,那么就把这 的样本称为袋外数据 oob(out-of-bag)。由于 oob 没有用于训练决策树,因此可用于后续对该决策树的泛化能力评估。

分类模型 SVM

https://zhuanlan.zhihu.com/p/77750026

SVM 三宝: 间隔,对偶,核技巧。它属于判别模型。Support Vector Machine

  • **支持向量:**在求解的过程中,会发现只根据部分数据就可以确定分类器,这些数据称为支持向量。
  • 支持向量机(SVM):其含义是通过支持向量运算的分类器。

SVM 是一种二分类模型, 它的目的是寻找一个超平面来对样本进行分割,分割的依据是间隔最大化,最终转化为一个凸二次规划问题来求解。

基础准备

1. 线性可分

是 n 维空间中的两个点集, 如果存在 n 维向量 和实数 , 使得:

则称 线性可分。

2. 最大间隔超平面

能够将 完全正确分开的 就成了一个超平面。

为了使得这个超平面更具鲁棒性,我们会去找最佳超平面,以最大间隔把两类样本分开的超平面,也称之为最大间隔超平面

  • 两类样本分别分割在该超平面的两侧
  • 两侧距离超平面最近的样本点到超平面的距离被最大化了

3. 什么是支持向量?

训练数据集中与分离超平面距离最近的样本点成为支持向量

1

4. SVM 能解决哪些问题?

  • **线性分类:**对于n维数据,SVM 的目标是找到一个 n-1 维的最佳超平面来将数据分成两部分。

    通过增加一个约束条件: 要求这个超平面到每边最近数据点的距离是最大的。

  • 非线性分类: SVM通过结合使用拉格朗日乘子法和KTT条件,以及核函数可以生产线性分类器

5. 支持向量机的分类

  • 硬间隔SVM(线性可分SVM): 当训练数据可分时,通过间隔最大化,学习一个线性表分类器。
  • 软间隔SVM(线性SVM):当训练数据接近线性可分时,通过软间隔最大化,学习一个线性分类器。
  • Kernel SVM: 当训练数据线性不可分时,通过使用核技巧及软间隔最大化,学习非线性SVM。

必会:硬间隔最大化 –> 学习的对偶问题 –> 软间隔最大化 –> 非线性支持向量机(核技巧)

硬间隔 SVM

1. 几何间隔与函数间隔

2. SVM 最优化问题

任意分离超平面可定义为:

二维空间中点 到直线 的距离公式为:

扩展到n维空间中,任意点 到超平面 的距离为:

假设,支持向量到超平面的距离为 ,那么就有:

稍作转化可得到:

考虑到 为正数,我们暂且令它为 1(之所以令它等于 1,是为了方便推导和优化,且这样做对目标函数的优化没有影响):

两个方程合并,则有:

那么我们就得到了最大间隔超平面的上下两个超平面:

2

两个异类超平面的公式分别为:

那么两个异类超平面之间的间隔为:

我们的目的是最大化这种间隔:

那么我们的最优化问题为:

3. 对偶问题

1. 拉格朗日乘数法 - 等式约束优化问题

高等数学中,其等式约束优化问题为:

那么令:

  • : Lagrange 函数
  • : Lagrange 乘子,没有非负要求

利用必要条件找到可能的极值点,我们得到如下的方程组:

等式约束下的Lagrange 乘数法引入了 个 Lagrange 乘子,我们将 一视同仁,将 也看做优化变量,那么共有 个优化变量。

2. 拉格朗日乘数法 - 不等式约束优化问题

对于不等式约束优化问题,其主要思想在于将不等式约束条件转变为等式约束条件,引入松弛变量,将松弛变量也是为优化变量。

3

对于我们的问题:

引入松弛变量 得到:

这里加平方主要为了不再引入新的约束条件,如果只引入 那我们必须要保证 才能保证 ,这不符合我们的意愿。

此时,我们就将不等式约束转化为等式约束,并得到 Lagrange 函数:

那么我们得到方程组有:

针对 有两种情况:

  • :此时约束条件 不起作用且
  • : 此时 , 可以理解为约束条件 起作用了, 且

综合可得:, 且在约束条件起作用时 ; 约束不起作用时,

此时,方程组转化为:

以上便是不等式约束优化优化问题的 KKT(Karush-Kuhn-Tucker) 条件 称为 KKT 乘子。

KTT 条件中,对于不同样本点来说

  • 支持向量 , 此时 即可
  • 其余向量 , 此时

回到原优化问题中:

由于 , 那么问题可以转化为:

假设我们找到了最佳的参数 使得 ,又因为 , 因此有 , 我们需要找到最佳的参数 , 使得 接近 p, 此时问题转化为:

4. 引入对偶问题

  • 弱对偶性: 最大的里面挑出来的最小的也要比最小的里面挑出来的最大的要大

  • 强对偶性:KKT 条件是强对偶性的充要条件。

5. SVM 优化

  • SVM 的优化问题为:

  • 构造拉格朗日函数:

  • 利用强对偶性转化:

    对参数 求偏导有:

    得到:

    将两式带入到 中有:

  • 求解模型:

6. 软间隔SVM

软间隔允许部分样本点不满足约束条件:

Kernel SVM

1. 思想

对于在有限维度向量空间中线性不可分的样本,我们将其映射到更高维度的向量空间里,再通过间隔最大化的方式,学习得到支持向量机,就是非线性 SVM。

用 x 表示原来的样本点,用 表示 x 映射到新特征空间后的新向量。那么分割超平面可以表示为:

此时,非线性 SVM 的对偶问题转化为:

2. 核函数的作用

  • 目的: 将原坐标系中线性不可分数据通过核函数映射到另一空间,尽量使数据在新的空间里线性可分。

2. 常见核函数

  • 线性核函数:

QA

1. SVM 中的支持向量是什么意思?

10.svm

如上图所示,我们在获得分离超平面时,并非所有的点都对分离超平面的位置起决定作用。

其实在特别远的区域,哪怕你增加10000个样本点,对于超平面的位置,也是没有作用的,因为分割线是由几个关键点决定的(图上三个),这几个关键点支撑起了一个分离超平面,所以这些关键点,就是支持向量

2. 什么是SVM ?

SVM 是一种二类分类模型。它的基本思想是在特征空间中寻找间隔最大的分离超平面使数据得到高效的二分类, 主要分三种情况:

  • 当训练样本线性可分时,通过硬间隔最大化,学习一个线性分类器,即线性可分支持向量机;
  • 当训练数据近似线性可分时,引入松弛变量,通过软间隔最大化,学习一个线性分类器,即线性支持向量机
  • 当训练数据线性不可分时,通过使用核技巧及软间隔最大化,学习非线性支持向量机。

3. SVM 为何采用间隔最大化?

当训练数据线性可分时,存在无穷个分离超平面可以将两类数据正确分开。

  • 感知机利用误分类最小策略,求得分离超平面,不过此时的解有无穷多个。
  • 线性可分支持向量机利用间隔最大化求得最优分离超平面,这时,解是唯一的。

SVM 求得的分隔超平面所产生的分类结果是最鲁棒的,对未知实例的泛化能力最强。

4. 为何要讲求解 SVM 的原始问题转换为其对偶问题?

  • 对偶问题往往更易求解

    当我们寻找约束存在时的最优点的时候,约束的存在虽然减小了需要搜寻的范围,但是却使问题变得更加复杂。为了使问题变得易于处理,我们的方法是把目标函数和约束全部融入一个新的函数,即拉格朗日函数,再通过这个函数来寻找最优点。

  • 自然引入核函数,进而推广到非线性分类问题

5. SVM 与 LR 的区别

  • LR是参数模型,SVM为非参数模型。
  • LR采用的损失函数为logisticalloss,而SVM采用的是hingeloss。
  • 在学习分类器的时候,SVM只考虑与分类最相关的少数支持向量点。
  • LR的模型相对简单,在进行大规模线性分类时比较方便。

6. SVM如何处理多分类问题?

  • 直接法:直接在目标函数上修改,将多个分类面的参数求解合并到一个最优化问题里面。看似简单但是计算量却非常的大。
  • 间接法:对训练器进行组合。其中比较典型的有一对一,和一对多。

一对多: 对每个类都训练出一个分类器,由svm是二分类,所以将此而分类器的两类设定为目标类为一类,其余类为另外一类。这样针对k个类可以训练出k个分类器,当有一个新的样本来的时候,用这k个分类器来测试,那个分类器的概率高,那么这个样本就属于哪一类。这种方法效果不太好,bias 比较高。

一对一: 针对任意两个类训练出一个分类器,如果有 k 类,一共训练出 个分类器,这样当有一个新的样本要来的时候,用这 个分类器来测试,每当被判定属于某一类的时候,该类就加一,最后票数最多的类别被认定为该样本的类。

7. SVM 软间隔与硬间隔表达式

  • 硬间隔:

  • 软间隔:

8. 核函数的种类和应用场景

  • 线性核函数:主要用于线性可分的情形。参数少,速度快。
  • 多项式核函数:
  • 高斯核函数:主要用于线性不可分的情形。参数多,分类结果非常依赖于参数。
  • sigmoid 核函数:
  • 拉普拉斯核函数:

如果feature数量很大,跟样本数量差不多,建议使用LR或者 Linear kernel 的SVM。
如果 feature 数量较少,样本数量一般,建议使用 Gaussian Kernel 的SVM。

9. SVM 损失函数是什么?

10. 核函数的作用是啥?

核函数能够将特征从低维空间映射到高维空间, 这个映射可以把低维空间中不可分的两类点变成线性可分的。

11. SVM 为何能用对偶函数求解?

对偶将原始问题中的约束转为了对偶问题中的等式约束, 而且更加方便了核函数的引入, 同时也改变了问题的复杂度, 在原始问题下, 求解问题的复杂度只与样本的维度有关, 在对偶问题下, 只与样本的数量有关。

12. SVM 和全部数据有关还是和局部数据有关?

SVM 只和分类界限上的支持向量点有关, 换而言之只和局部数据有关。

13. 为什么高斯核能够拟合无穷维度?

因为将泰勒展开式代入高斯核,将会得到一个无穷维度的映射。

14. LR 与 SVM 的区别?

  • LR是参数模型,SVM是非参数模型
  • 从目标函数来看,区别在于逻辑回归采用的是logistical loss,SVM采用的是hinge loss。这两个损失函数的目的都是增加对分类影响较大的数据点的权重,减少与分类关系较小的数据点的权重。
  • SVM的处理方法是只考虑支持向量,也就是和分类最相关的少数点,去学习分类器。而逻辑回归通过非线性映射,大大减小了离分类平面较远的点的权重,相对提升了与分类最相关的数据点的权重。
  • 逻辑回归相对来说模型更简单,好理解,特别是大规模线性分类时比较方便。而SVM的理解和优化相对来说复杂一些,SVM转化为对偶问题后,分类只需要计算与少数几个支持向量的距离,这个在进行复杂核函数计算时优势很明显,能够大大简化模型和计算。
  • logic 能做的 svm能做,但可能在准确率上有问题,svm能做的logic有的做不了。

回归模型 线性回归

简单来说,线性回归算法就是找到一条直线(一元线性回归)或一个平面(多元线性回归)能够根据输入的特征向量来更好的预测输出y的值。

其本质含义在于 X 与 Y 是线性相关的。

1. 线性回归如何训练?

在线性回归中, 我们可以通过两种方法来求取参数 , 一种是采用正规方程, 一种是采用梯度下降方法

1. 损失函数

2. 正规方程

我们使用 求导, 得到:

令上式为0,我们可以得到 的值为:

我们可以直接通过矩阵运算来求出参数 的解。 而上式我们发现其涉及到了矩阵的可逆问题,如果 可逆,那么参数 的解唯一如果不可逆, 则此时就无法使用正规方程的方法来解。

3. 梯度下降法

我们可以采用批量梯度下降算法, 此时有:

4. 两种方法的比较

  • 梯度下降中需要选择适当的学习率
  • 梯度下降法中需要多次进行迭代,而正规方程只需要使用矩阵运算就可以完成
  • 梯度下降算法对多特征适应性较好,能在特征数量很多时仍然工作良好, 而正规方程算法复杂度为 ,所以如果特征维度太高(特别是超过 10000 维),那么不宜再考虑该方法。
  • 正规方程中矩阵需要可逆。

岭回归

岭回归本质上是 线性回归 + L2 正则化

岭回归与线性回归

线性回归中通过正规方程得到的 w 的估计:

但是,当我们有 N 个样本,每个样本有 , 当 N < p 时, 不可逆, 无法通过正规方程计算,容易造成过拟合。

岭回归通过在矩阵 上加一个 来使得矩阵可逆, 此时的 w 的估计:

而岭回归本质上是对 进行 L2 正则化, 此时的 表示为:

那么对 的极大似然估计有:

那么我们就解得:

因此说, 岭回归本质上是 线性回归 + L2 正则化, 从而达到抑制过拟合的效果。

Lasso 回归

Lasso 回归的本质是 线性回归 + L1 正则化

ElasticNet 回归

ElasticNet 回归 本质上是线性回归 + L1正则化 + L2 正则化。

LWR 局部加权回归

在线性回归中, 由于最终拟合出来的曲线是一条直线,其拟合能力极为有限(也可以解释为线性回归所求的是具有最小均方误差的无偏估计),因此很容易造成欠拟合现象, 而针对这个问题,有人提出了局部线性回归(LWR)。

局部加权回归其思想很简单: 我们对一个输入 w 进行预测时,赋予了 x 周围点不同的权值,距离 x 越近,权重越高。整个学习过程中误差将会取决于 x 周围的误差,而不是整体的误差,这也就是局部一词的由来。

在LWR中, 其损失函数为:

此时,使用回归方程求得:

而通常, 服从高斯分布, 在x周围指数型衰减;

其中, k 值越小,则靠近预测点的权重越大,而远离预测点的权重越小。所以参数k的值决定了权重的大小。

  • k越大权重的差距就越小,k越小权重的差距就很大,仅有局部的点参与进回归系数的求取,其他距离较远的权重都趋近于零。
  • 如果k去进入无穷大,所有的权重都趋近于1,W也就近似等于单位矩阵,局部加权线性回归变成标准的无偏差线性回归,会造成欠拟合的现象;
  • 当k很小的时候,距离较远的样本点无法参与回归参数的求取,会造成过拟合的现象。

QA

1. 最小二乘法估计

其中有:

那 么,最终就得到:

考虑到 的结果其实都是一维实数且二者为转置,因此,二者的值相等, 那么就有:

那么就有:

从而就得到:

2. 最小二乘法的几何解释

3. 从概率角度看最小二乘法

最小二乘法隐藏的一个条件是: 误差服从正态分布。

我们假设起始条件:

假设误差服从正态分布,那么则有:

那么当噪声服从正态分布时,输出值也服从正态分布:

极大似然过程推导:

我们最终是要用极大似然估计

4. 推一下线性回归的反向传播

5. 从贝叶斯角度看线性回归

https://www.bilibili.com/video/av31989606/?p=4

6. 什么时候使用岭回归 ?

如果样本数据过少导致线性回归拟合较差,则考虑采用岭回归。如何输入特征的维度很高,而且是稀疏线性关系的话, 岭回归就不太合适,考虑使用Lasso回归。

7. 什么时候使用 L1 正则化?

L1正则化(Lasso回归)可以使得一些特征的系数变小,甚至还使一些绝对值较小的系数直接变为0,从而增强模型的泛化能力 。对于高的特征数据,尤其是线性关系是稀疏的,就采用L1正则化(Lasso回归),或者是要在一堆特征里面找出主要的特征,那么L1正则化(Lasso回归)更是首选了。

回归模型 岭回归

岭回归本质上是 线性回归 + L2 正则化

岭回归与线性回归

线性回归中通过正规方程得到的 w 的估计:

但是,当我们有 N 个样本,每个样本有 , 当 N < p 时, 不可逆, 无法通过正规方程计算,容易造成过拟合。

岭回归通过在矩阵 上加一个 来使得矩阵可逆, 此时的 w 的估计:

而岭回归本质上是对 进行 L2 正则化, 此时的 表示为:

那么对 的极大似然估计有:

那么我们就解得:

因此说, 岭回归本质上是 线性回归 + L2 正则化, 从而达到抑制过拟合的效果。


QA

1. 什么时候使用岭回归 ?

如果样本数据过少导致线性回归拟合较差,则考虑采用岭回归。如何输入特征的维度很高,而且是稀疏线性关系的话, 岭回归就不太合适,考虑使用Lasso回归。

模型 LDA

LDA 叫做线性判别分析,又叫做Fisher 线性判别函数, 其是一种有监督的降维技术,其思想为:投影后类内方差最小,类间方差最大。

简单来说,我们将数据向低维超平面上投影时, 投影后希望每一种类别数据的投影点尽可能的接近,而不同类别的数据的类别中心点的距离尽可能的大。

模型 树回归

CART 用于回归

https://blog.csdn.net/weixin_36586536/article/details/80468426

集成学习 GBDT

1. Boosting 思想

Boosting 基于串行策略, 各个基分类器之间有依赖。

  1. 先从初始训练集训练一个弱学习器,初始训练集各个样本权重相同
  2. 根据上一个弱学习器的表现,调整样本权重,是的分类错误的样本得到更多关注
  3. 基于调整后的样本分布,训练下一个弱学习器、
  4. 测试时,对各基学习器加权得到最终结果

2. GBDT

GBDT , Gradient Boosting Decision Tree, 叫 梯度提升决策树。

1. GBDT 思想

集成学习 LightGBM

集成学习 XGBoost

XGBoost 是 eXtreme Gradient Boosting 的缩写称呼,它是一个非常强大的 Boosting 算法工具包,优秀的性能(效果与速度)让其在很长一段时间内霸屏数据科学比赛解决方案榜首,现在很多大厂的机器学习方案依旧会首选这个模型。

XGBoost 在并行计算效率、缺失值处理、控制过拟合、预测泛化能力上都变现非常优秀。本文我们给大家详细展开介绍 XGBoost,包含「算法原理」和「工程实现」两个方面。

🚀无监督学习 聚类、降维

无监督学习是一种机器学习的训练方式,它本质上是一个统计手段,在没有标签的数据里可以发现潜在的一些结构的一种训练方式。

它主要具备3个特点:

  1. 无监督学习没有明确的目的
  2. 无监督学习不需要给数据打标签
  3. 无监督学习无法量化效果

案例

案例1:发现异常

有很多违法行为都需要”洗钱”,这些洗钱行为跟普通用户的行为是不一样的,到底哪里不一样?

如果通过人为去分析是一件成本很高很复杂的事情,我们可以通过这些行为的特征对用户进行分类,就更容易找到那些行为异常的用户,然后再深入分析他们的行为到底哪里不一样,是否属于违法洗钱的范畴。

通过无监督学习,我们可以快速把行为进行分类,虽然我们不知道这些分类意味着什么,但是通过这种分类,可以快速排出正常的用户,更有针对性的对异常行为进行深入分析。

案例2:用户细分

这个对于广告平台很有意义,我们不仅把用户按照性别、年龄、地理位置等维度进行用户细分,还可以通过用户行为对用户进行分类。

通过很多维度的用户细分,广告投放可以更有针对性,效果也会更好。

案例3:推荐系统

大家都听过”啤酒+尿不湿”的故事,这个故事就是根据用户的购买行为来推荐相关的商品的一个例子。

比如大家在淘宝、天猫、京东上逛的时候,总会根据你的浏览行为推荐一些相关的商品,有些商品就是无监督学习通过聚类来推荐出来的。系统会发现一些购买行为相似的用户,推荐这类用户最”喜欢”的商品。

聚类 KNN

K-NN(K-nearest neighbors)

K-NN算法是一种最简单的分类算法,通过识别被分成若干类的数据点,以预测新样本点的分类。K-NN是一种非参数的算法,是“懒惰学习”的著名代表,它根据相似性(如,距离函数)对新数据进行分类。

KNN算法是分类算法的一种,也属于监督学习算法,其基本思想为:

  • 当输入一个新的样本时,将新数据的每个特征与样本集中每个样本数据的特征进行比较。

  • 从样本集中选取最相近的 K 个样本,然后依据某种决策原则(少数服从多数)来判定这个新样本的 label。

在KNN算法中,有三个主要要素:距离度量,K 的取值,分类决策规则。

算法步骤

  • 计算新数据与数据集中所有样本之间的距离, 距离度量公式可以选择多种,如欧式距离,曼哈顿距离等。可以参见:[基础理论 - 距离度量方法](./基础理论 - 距离度量方法.md)

  • 按照距离,将样本按照距离值进行排序

  • 选取与当前数据距离最小的 K 个点。

  • 返回这 K 个点的 label, 依据某种决策原则来判定这个新数据的 label 。

K 的选择

  • 如果 K 较小,预测结果会对邻近的点十分敏感,如果邻近点恰好是噪声,则很容易预测错误。 换个角度说说, K的减小意味着模型变得复杂,容易发生过拟合。
  • 如果K 较大, 此时不相似的样本也会对预测产生作用,使得预测发生错误。换个角度说,K的增大意味着模型变得简单,容易发生欠拟合。

K-NN能很好地处理少量输入变量(p)的情况,但当输入量非常大时就会出现问题。

优点:

  1. 简单有效,容易理解和实现。
  2. 重新训练的代价较低(类别体系的变化和训练集的变化)。
  3. 由于KNN方法主要依赖周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合。
  4. 适合处理多模分类和多标签分类问题。

缺点:

  1. 是lazy learning方法(决策在测试时生成),比一些积极学习的算法要慢;
  2. 计算量比较大(需要计算到所有样本点的距离),需对样本点进行剪辑;
  3. 样本不平衡会导致预测偏差较大,可采用加权投票法改进;
  4. 容易对维度灾难敏感;
  5. 类别评分不是规格化的(不像概率评分)。

QA

1. KNN 中为何采用欧式距离而不采用曼哈顿距离?

我们不用曼哈顿距离,因为它只计算水平或垂直距离,有维度的限制。另一方面,欧式距离可用于任何空间的距离计算问题。因为,数据点可以存在于任何空间,欧氏距离是更可行的选择。例如:想象一下国际象棋棋盘,象或车所做的移动是由曼哈顿距离计算的,因为它们是在各自的水平和垂直方向的运动。

2.

聚类 聚类算法

聚类 谱聚类

降维 PCA


QA

1. PCA 中第一主成分是第一的原因?

https://www.nowcoder.com/questionTerminal/7e9febebe3d3467ca5ea17e013d416f0

2. 讲一下 PCA

PCA是比较常见的线性降维方法,通过线性投影将高维数据映射到低维数据中。 所期望的是在投影的维度上,新特征自身的方差尽量大,方差越大特征越有效,尽量使产生的新特征间的相关性越小。

PCA算法的具体操作为对所有的样本进行中心化操作,计算样本的协方差矩阵,然后对协方差矩阵做特征值分解,取最大的n个特征值对应的特征向量构造投影矩阵。

🚀强化学习的主流算法 免模型学习、有模型学习

强化学习(reinforcement learning)

强化学习算法的思路非常简单,以游戏为例,如果在游戏中采取某种策略可以取得较高的得分,那么就进一步“强化”这种策略,以期继续取得较好的结果。这种策略与日常生活中的各种“绩效奖励”非常类似。我们平时也常常用这样的策略来提高自己的游戏水平。

在 Flappy bird 这个游戏中,我们需要简单的点击操作来控制小鸟,躲过各种水管,飞的越远越好,因为飞的越远就能获得更高的积分奖励。

这就是一个典型的强化学习场景:

  • 机器有一个明确的小鸟角色——代理
  • 需要控制小鸟飞的更远——目标
  • 整个游戏过程中需要躲避各种水管——环境
  • 躲避水管的方法是让小鸟用力飞一下——行动
  • 飞的越远,就会获得越多的积分——奖励

在介绍详细算法之前,我们先来了解一下强化学习算法的2大分类。这2个分类的重要差异是:智能体是否能完整了解或学习到所在环境的模型

  • 有模型学习(Model-Based)对环境有提前的认知,可以提前考虑规划,但是缺点是如果模型跟真实世界不一致,那么在实际使用场景下会表现的不好。

  • 免模型学习(Model-Free)放弃了模型学习,在效率上不如前者,但是这种方式更加容易实现,也容易在真实场景下调整到很好的状态。所以免模型学习方法更受欢迎,得到更加广泛的开发和测试。

  • 免模型学习 – 策略优化(Policy Optimization)
    这个系列的方法将策略显示表示为: \pi_{\theta}(a|s) 。 它们直接对性能目标 J(\pi_{\theta}) 进行梯度下降进行优化,或者间接地,对性能目标的局部近似函数进行优化。优化基本都是基于 同策略 的,也就是说每一步更新只会用最新的策略执行时采集到的数据。策略优化通常还包括学习出 V_{\phi}(s) ,作为 V^{\pi}(s) 的近似,该函数用于确定如何更新策略。

基于策略优化的方法举例:

  • A2C / A3C, 通过梯度下降直接最大化性能

  • PPO , 不直接通过最大化性能更新,而是最大化 目标估计 函数,这个函数是目标函数 J(\pi_{\theta}) 的近似估计。

  • 免模型学习 – Q-Learning
    这个系列的算法学习最优行动值函数 Q^*(s,a) 的近似函数: Q_{\theta}(s,a) 。它们通常使用基于 贝尔曼方程 的目标函数。优化过程属于 异策略 系列,这意味着每次更新可以使用任意时间点的训练数据,不管获取数据时智能体选择如何探索环境。对应的策略是通过 Q^and \pi^ 之间的联系得到的。智能体的行动由下面的式子给出:

基于 Q-Learning 的方法

  • DQN, 一个让深度强化学习得到发展的经典方法

  • 以及 C51, 学习关于回报的分布函数,其期望是 Q^*

  • 有模型学习 – 纯规划
    这种最基础的方法,从来不显示的表示策略,而是纯使用规划技术来选择行动,例如 模型预测控制 (model-predictive control, MPC)。在模型预测控制中,智能体每次观察环境的时候,都会计算得到一个对于当前模型最优的规划,这里的规划指的是未来一个固定时间段内,智能体会采取的所有行动(通过学习值函数,规划算法可能会考虑到超出范围的未来奖励)。智能体先执行规划的第一个行动,然后立即舍弃规划的剩余部分。每次准备和环境进行互动时,它会计算出一个新的规划,从而避免执行小于规划范围的规划给出的行动。

    • MBMF 在一些深度强化学习的标准基准任务上,基于学习到的环境模型进行模型预测控制
  • 有模型学习 – Expert Iteration
    纯规划的后来之作,使用、学习策略的显示表示形式: \pi_{\theta}(a|s) 。智能体在模型中应用了一种规划算法,类似蒙特卡洛树搜索(Monte Carlo Tree Search),通过对当前策略进行采样生成规划的候选行为。这种算法得到的行动比策略本身生成的要好,所以相对于策略来说,它是“专家”。随后更新策略,以产生更类似于规划算法输出的行动。

    • ExIt 算法用这种算法训练深层神经网络来玩 Hex
    • AlphaZero 这种方法的另一个例子

除了免模型学习和有模型学习的分类外,强化学习还有其他几种分类方式:

  • 基于概率 VS 基于价值
  • 回合更新 VS 单步更新
  • 在线学习 VS 离线学习

概率图模型 HMM

频率派 vs 贝叶斯派

对于有 n 个样本的样本集 以及参数 , 那么有 服从概率分布

频率派

频率派认为 是一个未知的常量, 数据 是一个随机变量,其服从一定的概率分布, 目的是通过极大似然估计 + 随机变量 来估计出未知参数

贝叶斯派

贝叶斯派认为 是一个随机变量,其服从一定的概率分布 。其采用最大后验估计来计算

  • 先验: , 似然: , 后验:

极大似然估计 vs 最大后验估计

1. 极大似然估计 - MLE

  • 原理:利用已知的样本结果,反推最有可能(最大概率)导致这样结果的参数值。

  • 极大似然估计提供了一种给定观察数据来评估模型参数的方法:模型已定,参数未知。经过若干次实验,观察结果,利用实验结果得到某个参数值能够使得样本出现的概率为最大,称为极大似然估计。

  • 离散情况下参数 的似然函数:

  • 极大似然估计: 对于给定的样本值 有:

  • 使得似然函数 达到最大值的参数值 称为未知数 的最大似然估计值。

2. 最大后验估计 - MAP

MAP 的基础是贝叶斯公式:

MAP 优化的就是后验概率, 目的是通过观测值使得后验概率最大:


QA

1. 极大似然估计与最大后验概率的区别?

  • 最大似然估计提供了一种给定观察数据来评估模型参数的方法, 最大似然估计中的采样满足所有采样都是独立同分布的假设。
  • 最大后验概率是根据经验数据获难以观察量的点估计,与最大似然估计最大的不同是最大后验概率融入了要估计量的先验分布在其中,所以最大后验概率可以看做规则化的最大似然估计。

2. 概率与似然的区别

  • 概率是指在给定参数的情况下,样本的随机向量 的可能性。
  • 似然表示的是在给定样本 的情况下,参数 为真实值的可能性。

一般情况,对随机变量的取值用概率表示。而在非贝叶斯统计的情况下,参数为一个实数而不是随机变量,一般用似然来表示。

3. 贝叶斯派与频率学派的区别

  • 频率派认为抽样是无限的,在无限的抽样中,对于决策的规则可以很精确。贝叶斯派认为世界无时无刻不在改变,未知的变量和事件都有一定的概率,即后验概率是先验概率的修正。
  • 频率派认为模型参数是固定的,一个模型在无数次抽样后,参数是不变的。而贝叶斯学派认为数据才是固定的而参数并不是。
  • 频率派认为模型不存在先验而贝叶斯派认为模型存在先验。

础理论 SVM 核方法

核方法作用

  • 从模型角度:非线性带来高维转换
  • 从优化角度:对偶表示带来内积

正定核

预处理 数据预处理

数据清洗

数据清洗主要包括数据采样样本过滤

1. 样本采样

  • 分类问题: 需要注意样本均衡问题,合适选择正负比例。
  • 回归问题: 需要采集数据。
  • 对于采样得到的样本,根据需要,需要设定样本权重。
  • 当模型不能使用全部的数据来训练时,需要对数据进行采样,设定一定的采样率。

2. 样本过滤

  • 结合业务情况进行数据的过滤

  • 异常点检测

    • 偏差检测,例如聚类,最近邻等。
    • 基于统计的异常点检测算法
      例如极差,四分位数间距,均差,标准差等,这种方法适合于挖掘单变量的数值型数据。全距(Range),又称极差,是用来表示统计资料中的变异量数(measures of variation) ,其最大值与最小值之间的差距;四分位距通常是用来构建箱形图,以及对概率分布的简要图表概述。
    • 基于距离的异常点检测算法,主要通过距离方法来检测异常点,将数据集中与大多数点之间距离大于某个阈值的点视为异常点,主要使用的距离度量方法有绝对距离 ( 曼哈顿距离 ) 、欧氏距离和马氏距离等方法。
    • 基于密度的异常点检测算法,考察当前点周围密度,可以发现局部异常点,例如LOF算法

预处理 - 特征工程

如何处理数据中的缺失值

有些特征可能因为无法采样或者没有观测值而缺失,此时需要对这些缺失的特征值进行特殊处理。

1. 缺失值较多

如果该特征中的缺失值较多,则应该直接舍弃,否则反而可能引入较大噪声,造成反效果。

2. 缺失值较少

即当缺失值在 10% 以内时,我们可以采用多种方式处理:

  • 将缺失值当一个特征处理,用 一个异常值表示, 如0

    1
    data_train.fillna(0) 
  • 用均值填充

    通常一个策略是取相同 label 的数据的均值

    1
    data_train.fillna(data_train.mean()) 
  • 以上下数据填充

    1
    2
    data_train.fillna(method='pad')  # 上一个数据填充
    data_train.fillna(method='bfill') # 下一个数据填充
  • 插值法

    1
    data_train.interpolate() # 即估计中间点的值
  • 用随机森林等算法拟合

    将数据分为有值和缺失值2份,对有值的数据采用随机森林拟合,然后对有缺失值的数据进行预测,用预测的值来填充。

特征常见处理手段

1.数值归一化

归一化的目的是将所有的特征都统一到一个大致相同的数值区间中。

从梯度下降的角度来看,对于两个特征x1,x2, x1的范围远远大于x2,在学习率相同的情况下,x1的更新速度会大于x2,需要较多的迭代才能得到最优解。

  • 函数归一化: min-max 归一化, 零均值归一化(参考 Normalization 一节)
  • 分维度归一化
  • 排序归一化

2. 离散化

连续值的离散化:

  • **等值划分:**将特征按照值域进行均分,每一段内的取值等同处理。例如某个特征的取值范围为[0,10],我们可以将其划分为10段,[0,1),[1,2),…,[9,10)。
  • 等量划分是根据样本总数进行均分,每段等量个样本划分为1段。

区别:例如距离特征,取值范围[0,3000000],现在需要切分成10段,如果按照等比例划分的话,会发现绝大部分样本都在第1段中。使用等量划分就会避免这种问题,最终可能的切分是[0,100),[100,300),[300,500),..,[10000,3000000],前面的区间划分比较密,后面的比较稀疏。

共线性问题

对于回归算法而言, 其首先假设回归模型的解释变量之间不存在线性关系, 即解释变量X1,X2,……,Xk中的任何一个都不能是其他解释变量的线性组合。如果违背这一假定,即线性回归模型中某一个解释变量与其他解释变量间存在线性关系,就称线性回归模型中存在多重共线性。

多重共线性违背了解释变量间不相关的古典假设,将给普通最小二乘法带来严重后果。

其实,简单来说,就是特征冗余,容易导致过拟合。

1. 如何判定共线性问题?

  • 相关性分析。当相关性系数高于0.8,表明存在多重共线性;但相关系数低,并不能表示不存在多重共线性
  • 方差膨胀因子VIF。当VIF大于5或10时,代表模型存在严重的共线性问题;
  • 条件系数检验。 当条件数大于100、1000时,代表模型存在严重的共线性问题。

2. 如何消除共线性问题?

通常可通过PCA降维、逐步回归法和LASSO回归等方法消除共线性。

如何进行特征选择?

1. 特征分类

  • 相关特征: 对于特定的任务和场景有一定帮助的属性,这些属性能有效提升算法性能。
  • 无关特征:在特定的任务和场景下完全无用的属性,这些属性对对象在本目标环境下完全无用。
  • 冗余特征:同样是在特定的任务和场景下具有一定帮助的属性,但这类属性已过多的存在,不具有产生任何新的信息的能力。

2. 如何考虑特征选择

可以从以下两个方面来选择特征:

  • 特征是否具有发散性:某个特征若在所有样本上的都是一样的或者接近一致,即方差非常小。 也就是说所有样本的都具有一致的表现,那这些就不具有任何信息。
  • 特征与目标的相关性:与目标相关性高的特征,应当优选选择。

3. 特征选择方法分类

  • 过滤法:按照发散性或者相关性对各个特征进行评分,设定阈值或者待选择阈值的个数,选择特征。
  • 包装法:根据目标函数(通常是预测效果评分),每次选择若干特征,或者排除若干特征。
  • 嵌入法:先使用某些机器学习的算法和模型进行训练,得到各个特征的权值系数,根据系数从大到小选择特征。

4. 特征选择目的

  • 减少特征维度,使模型泛化能力更强,减少过拟合;
  • 降低任务目标的学习难度;
  • 一组优秀的特征通常能有效的降低模型复杂度,提升模型效率

关联规则

https://www.jianshu.com/p/7d459ace31ab

关联规则挖掘是一种基于规则的机器学习算法,该算法可以在大数据库中发现感兴趣的关系。它的目的是利用一些度量指标来分辨数据库中存在的强规则。也即是说关联规则挖掘是用于知识发现,而非预测,所以是属于无监督的机器学习方法。

从所有可能规则的集合中选择感兴趣的规则需要利用一些度量方法来筛选和过滤,下面的三种方法。

关联规则的三个度

1. 支持度

支持度表示 item-set {X,Y} 在总 item-set 里出现的概率。其中, 表示总事务集, num()表示事务集里特定 item-set 出现的次数。比如: 表示总事务集的个数, 表示含有 {X,Y} 的事务集的个数(个数也叫次数)。

2. 置信度

置信度表示在先决条件X发生的情况下,由关联规则”X→Y“推出Y的概率。即在含有X的项集中,含有Y的可能性。

3. 提升度

提升度表示含有X的条件下,同时含有Y的概率,与Y总体发生的概率之比。

满足最小支持度和最小置信度的规则,叫做“强关联规则”。

  • ,“X→Y”是有效的强关联规则。
  • ,“X→Y”是无效的强关联规则。
  • 特别地,,X与Y相互独立。

QA

1. 判断规则的有效性

题目:已知有1000名顾客买年货,分为甲乙两组,每组各500人,其中甲组有500人买了茶叶,同时又有450人买了咖啡;乙组有450人买了咖啡,如表所示,题目:茶叶→咖啡是一条有效的关联规则吗?

组次 买茶叶的人数 买咖啡的人数
甲组(500人) 500 450
已组(500人) 0 450

解答:

  • 茶叶–> 咖啡的支持度为:
  • 茶叶–>咖啡的置信度为:
  • 茶叶–>咖啡的提升度为:

由于提升度Lift(X→Y) =1,表示X与Y相互独立,即是否有X,对于Y的出现无影响。也就是说,是否购买咖啡,与有没有购买茶叶无关联。即规则”茶叶→咖啡“不成立,或者说关联性很小,几乎没有,虽然它的支持度和置信度都高达90%,但它不是一条有效的关联规则。

2. 如果数据有问题,怎么处理?

  • 上下采样平衡正负样例比
  • 考虑缺失值
  • 数据归一化

深度学习

深度学习

深度学习、神经网络、机器学习、人工智能的关系

深度学习、机器学习、人工智能

简单来说:

  • 深度学习是机器学习的一个分支(最重要的分支)
  • 机器学习是人工智能的一个分支

深度学习、神经网络

深度学习的概念源于人工神经网络的研究,但是并不完全等于传统神经网络。

不过在叫法上,很多深度学习算法中都会包含”神经网络”这个词,比如:卷积神经网络、循环神经网络。

所以,深度学习可以说是在传统神经网络基础上的升级,约等于神经网络。

案例:别图片中的汉字

假设深度学习要处理的信息是“水流”,而处理数据的深度学习网络是一个由管道和阀门组成的巨大水管网络。网络的入口是若干管道开口,网络的出口也是若干管道开口。这个水管网络有许多层,每一层由许多个可以控制水流流向与流量的调节阀。根据不同任务的需要,水管网络的层数、每层的调节阀数量可以有不同的变化组合。对复杂任务来说,调节阀的总数可以成千上万甚至更多。水管网络中,每一层的每个调节阀都通过水管与下一层的所有调节阀连接起来,组成一个从前到后,逐层完全连通的水流系统。

图片转化为计算机能看懂的语言

那么,计算机该如何使用这个庞大的水管网络来学习识字呢?

比如,当计算机看到一张写有“田”字的图片,就简单将组成这张图片的所有数字(在计算机里,图片的每个颜色点都是用“0”和“1”组成的数字来表示的)全都变成信息的水流,从入口灌进水管网络。

识别“田”字

我们预先在水管网络的每个出口都插一块字牌,对应于每一个我们想让计算机认识的汉字。这时,因为输入的是“田”这个汉字,等水流流过整个水管网络,计算机就会跑到管道出口位置去看一看,是不是标记由“田”字的管道出口流出来的水流最多。如果是这样,就说明这个管道网络符合要求。如果不是这样,就调节水管网络里的每一个流量调节阀,让“田”字出口“流出”的水最多。

这下,计算机要忙一阵了,要调节那么多阀门!好在计算机的速度快,暴力的计算加上算法的优化,总是可以很快给出一个解决方案,调好所有阀门,让出口处的流量符合要求。

识别“申”字

下一步,学习“申”字时,我们就用类似的方法,把每一张写有“申”字的图片变成一大堆数字组成的水流,灌进水管网络,看一看,是不是写有“申”字的那个管道出口流水最多,如果不是,我们还得再调整所有的阀门。这一次,要既保证刚才学过的“田”字不受影响,也要保证新的“申”字可以被正确处理。

如此反复进行,知道所有汉字对应的水流都可以按照期望的方式流过整个水管网络。这时,我们就说,这个水管网络是一个训练好的深度学习模型了。当大量汉字被这个管道网络处理,所有阀门都调节到位后,整套水管网络就可以用来识别汉字了。这时,我们可以把调节好的所有阀门都“焊死”,静候新的水流到来。

一行字里面识别“田”和”申“

与训练时做的事情类似,未知的图片会被计算机转变成数据的水流,灌入训练好的水管网络。这时,计算机只要观察一下,哪个出水口流出来的水流最多,这张图片写的就是哪个字。

深度学习大致就是这么一个用人类的数学知识与计算机算法构建起来的整体架构,再结合尽可能多的训练数据以及计算机的大规模运算能力去调节内部参数,尽可能逼近问题目标的半理论、半经验的建模方式。

传统机器学习 VS 深度学习

传统机器学习和深度学习的相似点

在数据准备和预处理方面,两者是很相似的。

他们都可能对数据进行一些操作:

  • 数据清洗
  • 数据标签
  • 归一化
  • 去噪
  • 降维

传统机器学习和深度学习的核心区别

传统机器学习的特征提取主要依赖人工,针对特定简单任务的时候人工提取特征会简单有效,但是并不能通用。

深度学习的特征提取并不依靠人工,而是机器自动提取的。这也是为什么大家都说深度学习的可解释性很差,因为有时候深度学习虽然能有好的表现,但是我们并不知道他的原理是什么。

深度学习的优缺点

  • 优点

    1. 学习能力强
      从结果来看,深度学习的表现非常好,他的学习能力非常强。

    2. 覆盖范围广,适应性好
      深度学习的神经网络层数很多,宽度很广,理论上可以映射到任意函数,所以能解决很复杂的问题。

    3. 数据驱动,上限高
      深度学习高度依赖数据,数据量越大,他的表现就越好。在图像识别、面部识别、NLP 等部分任务甚至已经超过了人类的表现。同时还可以通过调参进一步提高他的上限。

    4. 可移植性好
      由于深度学习的优异表现,有很多框架可以使用,例如 TensorFlow、Pytorch。这些框架可以兼容很多平台。

  • 缺点

    1. 计算量大,便携性差
      深度学习需要大量的数据很大量的算力,所以成本很高。并且现在很多应用还不适合在移动设备上使用。目前已经有很多公司和团队在研发针对便携设备的芯片。这个问题未来会得到解决。

    2. 硬件需求高
      深度学习对算力要求很高,普通的 CPU 已经无法满足深度学习的要求。主流的算力都是使用 GPU 和 TPU,所以对于硬件的要求很高,成本也很高。

    3. 模型设计复杂
      深度学习的模型设计非常复杂,需要投入大量的人力物力和时间来开发新的算法和模型。大部分人只能使用现成的模型。

    4. 没有”人性”,容易存在偏见
      由于深度学习依赖数据,并且可解释性不高。在训练数据不平衡的情况下会出现性别歧视、种族歧视等问题。

几个典型的深度学习算法

卷积神经网络 CNN

CNN 的价值:

  • 能够将大数据量的图片有效的降维成小数据量(并不影响结果)
  • 能够保留图片的特征,类似人类的视觉原理

CNN 的基本原理:

  • 卷积层 – 主要作用是保留图片的特征
  • 池化层 – 主要作用是把数据降维,可以有效的避免过拟合
  • 全连接层 – 根据不同任务输出我们想要的结果

CNN 的实际应用:

  • 图片分类、检索
  • 目标定位检测
  • 目标分割
  • 人脸识别
  • 骨骼识别

循环神经网络 – RNN

RNN 是一种能有效的处理序列数据的算法。比如:文章内容、语音音频、股票价格走势…

之所以他能处理序列数据,是因为在序列中前面的输入也会影响到后面的输出,相当于有了“记忆功能”。但是 RNN 存在严重的短期记忆问题,长期的数据影响很小(哪怕他是重要的信息)。

于是基于 RNN 出现了 LSTM 和 GRU 等变种算法。这些变种算法主要有几个特点:

  • 长期信息可以有效的保留
  • 挑选重要信息保留,不重要的信息会选择“遗忘”

RNN 几个典型的应用如下:

  • 文本生成
  • 语音识别
  • 机器翻译
  • 生成图像描述
  • 视频标记

生成对抗网络 – GANs

假设一个城市治安混乱,很快,这个城市里就会出现无数的小偷。在这些小偷中,有的可能是盗窃高手,有的可能毫无技术可言。假如这个城市开始整饬其治安,突然开展一场打击犯罪的「运动」,警察们开始恢复城市中的巡逻,很快,一批「学艺不精」的小偷就被捉住了。之所以捉住的是那些没有技术含量的小偷,是因为警察们的技术也不行了,在捉住一批低端小偷后,城市的治安水平变得怎样倒还不好说,但很明显,城市里小偷们的平均水平已经大大提高了。

警察们开始继续训练自己的破案技术,开始抓住那些越来越狡猾的小偷。随着这些职业惯犯们的落网,警察们也练就了特别的本事,他们能很快能从一群人中发现可疑人员,于是上前盘查,并最终逮捕嫌犯;小偷们的日子也不好过了,因为警察们的水平大大提高,如果还想以前那样表现得鬼鬼祟祟,那么很快就会被警察捉住。为了避免被捕,小偷们努力表现得不那么「可疑」,而魔高一尺、道高一丈,警察也在不断提高自己的水平,争取将小偷和无辜的普通群众区分开。随着警察和小偷之间的这种「交流」与「切磋」,小偷们都变得非常谨慎,他们有着极高的偷窃技巧,表现得跟普通群众一模一样,而警察们都练就了「火眼金睛」,一旦发现可疑人员,就能马上发现并及时控制——最终,我们同时得到了最强的小偷和最强的警察。

深度强化学习 – RL

强化学习算法的思路非常简单,以游戏为例,如果在游戏中采取某种策略可以取得较高的得分,那么就进一步「强化」这种策略,以期继续取得较好的结果。这种策略与日常生活中的各种「绩效奖励」非常类似。我们平时也常常用这样的策略来提高自己的游戏水平。

总结

深度学习属于机器学习的范畴,深度学习可以说是在传统神经网络基础上的升级,约等于神经网络。

深度学习和传统机器学习在数据预处理上都是类似的。核心差别在特征提取环节,深度学习由机器自己完成特征提取,不需要人工提取。

深度学习的优点:

  • 学习能力强
  • 覆盖范围广,适应性好
  • 数据驱动,上限高
  • 可移植性好

深度学习的缺点:

  • 计算量大,便携性差
  • 硬件需求高
  • 模型设计复杂
  • 没有”人性”,容易存在偏见

在 Flappy bird 这个游戏中,我们需要简单的点击操作来控制小鸟,躲过各种水管,飞的越远越好,因为飞的越远就能获得更高的积分奖励。

这就是一个典型的强化学习场景:

  • 机器有一个明确的小鸟角色——代理
  • 需要控制小鸟飞的更远——目标
  • 整个游戏过程中需要躲避各种水管——环境
  • 躲避水管的方法是让小鸟用力飞一下——行动
  • 飞的越远,就会获得越多的积分——奖励

深度学习流程

1. 定义问题

确定是分类问题还是回归问题,还是无监督问题。

2. 探索和清洗数据

探索和进一步清洗数据集一直都是深度学习中最重要的一步。

3. 选择模型并探索模型结果

探索模型的结果,通常是需要对模型在验证集上的性能进行进一步的分析,这是如何进一步提升模型性能很重要的步骤。将模型在训练集和验证集都进行结果的验证和可视化,可直观的分析出模型是否存在较大偏差以及结果的正确性。

4. 监控训练和验证误差

首先很多情况下,我们忽略代码的规范性和算法撰写正确性验证,这点上容易产生致命的影响。

在训练和验证都存在问题时,首先请确认自己的代码是否正确。其次,根据训练和验证误差进一步追踪模型的拟合状态。若训练数据集很小,此时监控误差则显得格外重要。确定了模型的拟合状态对进一步调整学习率的策略的选择或者其他有效超参数的选择则会更得心应手。


模型提升策略

1. 数据角度

数据增强。 扩充数据集。

2. 模型角度

提高模型复杂度,更改模型结构。

3. 调参角度

4. 训练角度

深度学习脑图

flowchart LR
    A[深度学习]
    
    A --> B[Tirck]

    A --> C[卷积神经网络(CNN)]

    A --> D[循环神经网络(RNN)]

    A --> E[人工神经网络(ANN)]

Trick Dropout

  • 思想: 在每次训练过程中随机地忽略一些神经元。这些神经元被随机地“抛弃”了。也就是说它们在正向传播过程中对于下游神经元的贡献效果暂时消失了,反向传播时该神经元也不会有任何权重的更新。

  • **注意:**每次迭代的过程中,我们删除的神经单元是随机的,本次删除的与上次删除神经元是不一样的

简单来说,Dropout 通过参数共享提供了一种廉价的 Bagging 集成近似—— Dropout 策略相当于集成了包括所有从基础网络除去部分单元后形成的子网络。

QA

1. 为何 Dropout 能够解决过拟合?

  • 取平均的作用: 先回到正常的模型(没有dropout),我们用相同的训练数据去训练5个不同的神经网络,一般会得到5个不同的结果,此时我们可以采用 “5个结果取均值”或者“多数取胜的投票策略”去决定最终结果。这种“综合起来取平均”的策略通常可以有效防止过拟合问题。因为不同的网络可能产生不同的过拟合,取平均则有可能让一些“相反的”拟合互相抵消。

    dropout 掉不同的隐藏神经元就类似在训练不同的网络(随机删掉一半隐藏神经元导致网络结构已经不同),整个dropout过程就相当于 对很多个不同的神经网络取平均。而不同的网络产生不同的过拟合,一些互为“反向”的拟合相互抵消就可以达到整体上减少过拟合。

  • 减少神经元之间复杂的共适应关系: 因为dropout程序导致两个神经元不一定每次都在一个dropout网络中出现。(这样权值的更新不再依赖于有固定关系的隐含节点的共同作用,阻止了某些特征仅仅在其它特定特征下才有效果的情况)。 迫使网络去学习更加鲁棒的特征 (这些特征在其它的神经元的随机子集中也存在)。

    换句话说假如我们的神经网络是在做出某种预测,它不应该对一些特定的线索片段太过敏感,即使丢失特定的线索,它也应该可以从众多其它线索中学习一些共同的模式(鲁棒性)。(这个角度看 dropout就有点像L1,L2正则,减少权重使得网络对丢失特定神经元连接的鲁棒性提高)

2. Drpout 与 Bagging 有何不同?

  • 在 Bagging 的情况下,所有模型都是独立的;而在 Dropout 的情况下,所有模型共享参数,其中每个模型继承父神经网络参数的不同子集。
  • 在 Bagging 的情况下,每一个模型都会在其相应训练集上训练到收敛。而在 Dropout 的情况下,通常大部分模型都没有显式地被训练;取而代之的是,在单个步骤中我们训练一小部分的子网络,参数共享会使得剩余的子网络也能有好的参数设定。

3. Dropout 有什么缺陷?

dropout一大缺点就是代价函数J不再被明确定义,每次迭代,都会随机移除一些节点,如果再三检查梯度下降的性能,实际上是很难进行复查的。定义明确的代价函数J每次迭代后都会下降,因为我们所优化的代价函数J实际上并没有明确定义,或者说在某种程度上很难计算,所以我们失去了调试工具来绘制这样的图片。

我通常会关闭dropout函数,将keep-prob的值设为1,运行代码,确保J函数单调递减。然后打开dropout函数,希望在dropout过程中,代码并未引入bug。我觉得你也可以尝试其它方法,虽然我们并没有关于这些方法性能的数据统计,但你可以把它们与dropout方法一起使用。

Trick Normalization

归一化

1. 归一化手段

  • **Min-max 归一化:**当有新数据加入时, 可能导致max和min的变化, 需要重新定义。

  • **Zero-mean 归一化:**均值为0,标准差为1的标准正态分布。 z-score标准化方法适用于属性A的最大值和最小值未知的情况,或有超出取值范围的离群数据的情况。该种标准化方式要求原始数据的分布可以近似为高斯分布,否则效果会变得很糟糕。

2. Min-max 与 Zero-mean 区别

  • 对于输出结果范围有要求, 使用Min-max normalization
  • 数据较为稳定, 不存在极端最大值,最小值, 用归一化
  • 如果数据存在异常值或较多噪音, 使用标准化。

3. 为何归一化为何如此优秀?

归一化的本质就是线性变换。 线性变化的诸多良好性质,决定了为什么对数据进行改变后不会造成“失效”,还能提高数据的表现。

归一化加快了梯度下降求最优解的速度。

假定一个预测房价的例子,两个特征: 面积与房间数,那么则有: 表房间数, 表面积 , 现实中,面积范围往往在 , 而房间通常为 , 那么面积对模型的影响要更大一些,此时寻求最优解的过程为:

1

归一化后,寻求最优解的过程为:

在未归一化的时候, 由于 的更新幅度要比 小, 因此 的应该要比 要大,但是在实际中,我们使用常规梯度下降法时,我们各个的学习率都是一样的,这也就造成了 的更新会比较慢,结果就是寻求最优解的过程会走很多弯路导致模型收敛速度缓慢。

我们来实际举例, 假设在未归一化的时候, 我们的损失函数为:

那么经过归一化后,我们的损失函数可能就变为:

很明显可以看到,数据归一化后, 最优解的寻找过程会很平缓,更容易正确收敛到最优解。

其次,还有一些博客中提到,归一化有可能提高精度, 这在涉及到一些距离计算的算法时效果显著。

Batch Normalization

假设一个 batch 为 m 个输入 , BN 在这 m 个数据之间做 Normalization, 并学习参数

Layer Normalization

LN 不同于 BN, 其在层内进行 Normalization, 即直接对隐层单元的输出做 Normalization。最大的好处是不再依赖 batch size。

  • H: 某层中的隐层单元数

Weight Normalization

QA

1. 什么是 ICS?

ICS 指的是在训练过程中由于网络参数的变化而导致各层网络的输入分布发生了变化, 而深层网络通过层层叠加,高层的输入分布变化会非常剧烈,这就需要高层不断去重新适应底层的参数更新。而为了训好模型,我们需要非常谨慎的去设定学习率, 初始化权重等。

从数学角度来看,它指的是源空间与目标空间的条件概率是一致的,但是其边缘概率不同。 即对所有 , 但是

其实,通俗理解来说,就是对于神经网络的各层输出,由于经过了一系列的隐层操作,其分布显然与各层对应的输入数据分布不同,且这种差距会随着网络深度的增加而加大。而在训练过程中, 网络参数的变化会使得各层网络的输入分布发生变化,越深的网络,变化可能越大。

2. ICS 会导致什么问题?

  • 上层参数需要不断适应新的输入数据分布,降低学习速度
  • 下层输入的变化可能趋向于变大或变小,导致上层落入饱和区,使得学习过早停止。
  • 每层的更新都会影响到其它层,因此每层的参数更新策略需要尽可能的谨慎。

3. BN 到底解决了什么问题?

  • 解释1: 原论文说 BN 解决了 ICS 问题,但后续有论文推翻了这个结论,参见:《How Does Batch Normalization Help Optimization》

  • 解释2: 为了防止梯度消失,这也很好理解, BN 将激活函数的输入数据压缩在 N(0,1) 空间内,的确能够很大程度上减轻梯度消失问题。

  • 解释3: 来源于《How Does Batch Normalization Help Optimization》 , BN 使得优化空间更加平滑,具体来说,BN实际上是改变了损失函数的 lipschitz 性质, 使得梯度的改变变得很轻微,这使得我们可以采用更大的步长且仍然能够保持对实际梯度方向的精确估计。

    通俗来讲, 不进行BN, 损失函数不仅仅非凸且趋向于坑洼,平坦区域和极小值,这使得优化算法极不稳定,使得模型对学习率的选择和初始化方式极为敏感,而BN大大减少了这几种情况发生。

我个人更倾向于第三种解释。

4. BN 的优点与缺点

  • BN 的优点:

    • 加速网络训练(缓解梯度消失,支持更大的学习率)
    • 抑制过拟合
    • 降低了参数初始化的要求。
  • BN 的缺点:

    • 对 batch size的要求较高。这是因为如果 batch size 过小,无法估计出全局的样本分布
    • **训练和预测时有些差别。**训练时一个 batch 之间进行 Normalization, 预测时需要依靠训练时获得的 均值和方差来进行预测。

5. 为何训练时不采用移动平均?

参见: 《Batch Renormalization: Towards Reducing Minibatch Dependence in Batch-Normalized Models》

  • 使用 BN 的目的就是为了保证每批数据的分布稳定,使用全局统计量反而违背了这个初衷;
  • BN 的作者认为在训练时采用移动平均可能会与梯度优化存在冲突;

6. BN 与 LN 的区别是什么?

LN 对层进行 Normalization , BN 对 batch 进行 Normalization。 LN 摆脱了对 batch size 的依赖, 在 NLP 领域,使用极为广泛, 基本不用 BN。

我个人的认为是, BN 是对batch进行操作,然而, 语言的复杂度使得 一个 batch 的数据对于全局的数据分布估计极为不准,这使得 BN 的效果变得很差。

7. 什么时候使用 BN 或 LN?

  • 一般只在深层网络中使用, 比如在深层的 Transformer 中, LN 就起到了很关键的作用。
  • BN 与 LN 应用在非线性映射前效果更佳。
  • 当你发现你的网络训练速度慢,梯度消失,爆炸等问题时, 不妨考虑加入 BN 或 LN 来试试。
  • 使用 BN 时, 对 batch size 要求较高, 且在训练前需要对数据进行 shuffle。

8. BN 在何处做?

BN 可以对第 L 层激活函数输出值对第 L层激活函数的输入值进行 Normalization, 对于两个不同的位置,不少研究已经表明:放在第 L 层激活函数输出值会更好

9. 为什么要归一化?

  • 归一化的确可以避免一些不必要的数值问题。
  • 为了程序运行时收敛加快。
  • 统一量纲。样本数据的评价标准不一样,需要对其量纲化,统一评价标准。这算是应用层面的需求。
  • 避免神经元饱和。啥意思?就是当神经元的激活在接近 0 或者 1 时会饱和,在这些区域,梯度几乎为 0,这样,在反向传播过程中,局部梯度就会接近 0,这会有效地“杀死”梯度。
  • 保证输出数据中数值小的不被吞食。

Reference

[1] Batch Normalization

[2] Layer Normalization

[3] How Does Batch Normalization Help Optimization

[4] Batch Renormalization: Towards Reducing Minibatch Dependence in Batch-Normalized Models

深度学习中 Batch Normalization为什么效果好? - 知乎

深度学习中的Normalization模型

Trick 学习率衰减

为什么要进行学习率衰减?

随着训练的加深,当模型训练到一定程度后,损失将不再减少,这个时候模型的一阶梯度接近于0, 对应的 Hessian 矩阵通常是两种情况:

  • 正定,即所有特征值均为正,此时通常可以得到一个局部极小值,若这个局部极小值接近全局最小则模型已经能得到不错 的性能了,但若差距很大,则模型性能还有待于提升,通常情况下后者在训练初最常见。
  • 特征值有正有负,此时模型很可能陷入了鞍点,若陷入鞍点,模型性能表现就很差。

以上两种情况在训练初期以及中期,此时若仍然以固定的学习率,会使模型陷入左右来回的震荡或者鞍点,无法继续优化。所以,学习率衰减或者增大能帮助模型有效的减少震荡或者逃离鞍点。

学习率衰减策略

参见 500 questions 第14 章

Trick 提前终止


前期对该Trick的重视度不够, 想着,不就是过拟合吗? 我只要保存 验证集 loss 最低点的模型, 你过拟合管我什么事情, 然而, 上了 Bert + 中大规模数据集之后, 我才发现什么叫做噩梦 – 训练时间太 bb 长了吧。

那还能咋地, 你总不能把 epoch 数量设置的太小吧, 10 是比较基本的吧(看数据集),但这样跑也能跑个一天一夜,枯了。 这个时候这个Trick 就很有用了,大大节省模型训练时间。

提前终止指的是当验证集的误差连续 n次递增时停止训练。 一般情况下, 我会先将n设置为一个较大的数, 跑一个较大的 epoch(如20), 然后根据 loss 曲线来选择合适的 epoch 数量和 n, 接下来就欢快的嘿嘿嘿了。

需要注意的是,提前终止有其他很多策略,上面提到的只是很常用的一种,至于什么时候选择什么样的提前终止策略也是一个经验活, 还好, [1] 中为我们提供了一些参考, 值得一看。 由于本人经验时间优先,没有深入探讨,希望有大佬帮忙解惑。下面我简单提一下[1] 中是如何建议的。

Early Stop, but when? [1]

首先,思考一个问题: 如果我们以验证集loss最小值来作为保存模型的依据,那么这会不会对模型的泛化能力产生影响?我个人认为是不会,具体需要看Loss曲线图。一般而言,第一次跑的时候,我往往会设置一个很大的 epoch, 这样能够直观的从Loss曲线上看到很多信息,从而帮助我来选择更佳合适 epoch数量, 我个人一般取开始过拟合之后两个epoch作为epoch的最终数量。

我自己做实验发现,在验证集loss最低点不一定能够获得在测试集上最好的效果,有时候,最低点附近的一些点反而在测试集上表现更佳,但差别不大,这也是我认为不会影响模型泛化能力的一个依据, 而实际落地中,这点差别其实真的没有啥鸟用。

回到Trick, 文章谈到, 何时提前停止是对训练时间和泛化误差之间的权衡, 而如果我采用在验证集loss最低点存储模型的方式,那么何时提前停止就不再是对泛化误差的权衡了, 其变成了,如何选择何种的策略来对训练时间以及获取验证集loss全局最低点来做权衡,使得我们能够找到该点并保存模型,而不至于陷入一些困境[2]。

最后谈谈 Early Stop 策略, 选择合适的策略能够使得我们在合适的时间终止整个训练,从而节省时间。

Trick 正则化

https://blog.csdn.net/jinping_shi/article/details/52433975

https://zhuanlan.zhihu.com/p/38709373

https://blog.csdn.net/heyongluoyao8/article/details/49429629

1. L1 正则化 - 稀疏正则化

1-范数: 表示向量元素的绝对值之和。

不同于L2,L1 正则化使得权重值可能被减少到0。 因此,L1对于压缩模型很有用。

稀疏向量通常会有许多维度,如果再加上使用特征组合会导致包含更多的维度的。由于使用此类高维度特征向量,因此模型可能会非常庞大,并且需要大量的 RAM。

在高维度稀疏矢量中,最好尽可能使权重正好降至 0。正好为 0 的权重基本上会使相应特征从模型中移除。 将特征设为 0 可节省 RAM 空间,且可以减少模型中的噪点。

2. L2 正则化 – 权重衰减

2-范数: 表示向量元素绝对值的平方和再开方。

L2正则化又称权重衰减。因为其导致权重趋向于0(但不全是0)。

执行 L2 正则化对模型具有以下影响:

  • 使权重值接近于 0(但并非正好为 0)
  • 使权重的平均值接近于 0,且呈正态分布。

QA

1. 为何只对权重进行正则惩罚,而不针对偏置

在神经网络中,参数包括每一层仿射变换的权重偏置,我们通常只对权重做惩罚而不对偏置做正则惩罚。

精确拟合偏置所需的数据通常比拟合权重少得多。每个权重会指定两个变量如何相互作用。我们需要在各种条件下观察这两个变量才能良好地拟合权重。而每个偏置仅控制一个单变量。这意味着,我们不对其进行正则化也不会导致太大的方差。另外,正则化偏置参数可能会导致明显的欠拟合。

2. 权重衰减的目的

限制模型的学习能力,通过限制参数 θ 的规模(主要是权重 w 的规模,偏置 b 不参与惩罚),使模型偏好于权值较小的目标函数,防止过拟合。

3. L1 与 L2 的异同

  • 相同点:限制模型的学习能力,通过限制参数的规模,使模型偏好于权值较小的目标函数,防止过拟合。

  • 不同点:

    • L1是模型各个参数的绝对值之和;L2为各个参数平方和的开方值。
    • L1 正则化可以产生稀疏权值矩阵,即产生一个稀疏模型,可以用于特征选择;L2 会趋向于生成一个参数值很小的矩阵。
    • L1 适用于特征之间有关联的情况; L2 适用于特征之间没有关联的情况

4.为什么 L1 正则化 可以产生稀疏值,而 L2 不会?

添加 L1 正则化,相当于在 L1范数的约束下求目标函数 J 的最小值,下图展示了二维的情况:

L1

图中 J 与 L 首次相交的点就是最优解。L1 在和每个坐标轴相交的地方都会有“角”出现(多维的情况下,这些角会更多),在角的位置就会产生稀疏的解。而 J 与这些“角”相交的机会远大于其他点,因此 L1 正则化会产生稀疏的权值。

对于 L2 正则化来说,其二维平面下的图形为:

L2

如上图所示, 相比于 L1 正则化, L2 不会产生 “角”, 因此 J 与 L2 相交的点具有稀疏性的概率就会变得非常小。

5. 为何 L1 和 L2 正则化可以防止过拟合?

L1 & L2 正则化会使模型偏好于更小的权值。

简单来说,更小的权值意味着更低的模型复杂度,也就是对训练数据的拟合刚刚好,不会过分拟合训练数据(比如异常点,噪声),以提高模型的泛化能力。

此外,添加正则化相当于为模型添加了某种限制,规定了参数的分布,从而降低了模型的复杂度。模型的复杂度降低,意味着模型对于噪声与异常点的抗干扰性的能力增强,从而提高模型的泛化能力。 – 奥卡姆剃刀原理

主动学习

思路:通过机器学习的方法获取到那些比较难分类的样本数据,让人工再次确认和审核,然后将人工标注得到的数据再次使用有监督学习模型或半监督学习模型进行训练,逐步提升模型效果,将人工姜妍融入机器学习的模型中。

主动学习的流程:

  1. 机器学习模型:包括机器学习模型的训练和预测两部分;

https://zhuanlan.zhihu.com/p/301117945

卷积神经网络 CNN

卷积神经网络 – CNN 最擅长的就是图片的处理。它受到人类视觉神经系统的启发。

CNN 有2大特点:

  • 能够有效的将大数据量的图片降维成小数据量
  • 能够有效的保留图片特征,符合图片处理的原则

目前 CNN 已经得到了广泛的应用,比如:人脸识别、自动驾驶、美图秀秀、安防等很多领域。

CNN 解决了什么问题?

在 CNN 出现之前,图像对于人工智能来说是一个难题,有2个原因:

图像需要处理的数据量太大,导致成本很高,效率很低
图像在数字化的过程中很难保留原有的特征,导致图像处理的准确率不高

需要处理的数据量太大

图像是由像素构成的,每个像素又是由颜色构成的

现在随随便便一张图片都是 1000×1000 像素以上的, 每个像素都有RGB 3个参数来表示颜色信息。

假如我们处理一张 1000×1000 像素的图片,我们就需要处理3百万个参数!

1000×1000×3=3,000,000

这么大量的数据处理起来是非常消耗资源的,而且这只是一张不算太大的图片!

卷积神经网络 – CNN 解决的第一个问题就是「将复杂问题简化」,把大量参数降维成少量参数,再做处理。

更重要的是:我们在大部分场景下,降维并不会影响结果。比如1000像素的图片缩小成200像素,并不影响肉眼认出来图片中是一只猫还是一只狗,机器也是如此。

保留图像特征

图片数字化的传统方式我们简化一下,就类似下图的过程:

假如有圆形是1,没有圆形是0,那么圆形的位置不同就会产生完全不同的数据表达。但是从视觉的角度来看,图像的内容(本质)并没有发生变化,只是位置发生了变化。

所以当我们移动图像中的物体,用传统的方式的得出来的参数会差异很大!这是不符合图像处理的要求的。

而 CNN 解决了这个问题,他用类似视觉的方式保留了图像的特征,当图像做翻转,旋转或者变换位置时,它也能有效的识别出来是类似的图像。

那么卷积神经网络是如何实现的呢?在我们了解 CNN 原理之前,先来看看人类的视觉原理是什么?

人类视觉原理

人类的视觉原理如下:从原始信号摄入开始(瞳孔摄入像素 Pixels),接着做初步处理(大脑皮层某些细胞发现边缘和方向),然后抽象(大脑判定,眼前的物体的形状,是圆形的),然后进一步抽象(大脑进一步判定该物体是只气球)。下面是人脑进行人脸识别的一个示例:

对于不同的物体,人类视觉也是通过这样逐层分级,来进行认知的:

我们可以看到,在最底层特征基本上是类似的,就是各种边缘,越往上,越能提取出此类物体的一些特征(轮子、眼睛、躯干等),到最上层,不同的高级特征最终组合成相应的图像,从而能够让人类准确的区分不同的物体。

那么我们可以很自然的想到:可以不可以模仿人类大脑的这个特点,构造多层的神经网络,较低层的识别初级的图像特征,若干底层特征组成更上一层特征,最终通过多个层级的组合,最终在顶层做出分类呢?

答案是肯定的,这也是许多深度学习算法(包括CNN)的灵感来源。

典型的 CNN 由3个部分构成:

  1. 卷积层 – 主要作用是保留图片的特征
  2. 池化层 – 主要作用是把数据降维,可以有效的避免过拟合
  3. 全连接层 – 根据不同任务输出我们想要的结果

卷积层负责提取图像中的局部特征;
池化层用来大幅降低参数量级(降维);
全连接层类似传统神经网络的部分,用来输出想要的结果

卷积层

卷积——提取特征

卷积层的运算过程如下图,用一个卷积核扫完整张图片:

这个过程我们可以理解为我们使用一个过滤器(卷积核)来过滤图像的各个小区域,从而得到这些小区域的特征值。

在具体应用中,往往有多个卷积核,可以认为,每个卷积核代表了一种图像模式,如果某个图像块与此卷积核卷积出的值大,则认为此图像块十分接近于此卷积核。如果我们设计了6个卷积核,可以理解:我们认为这个图像上有6种底层纹理模式,也就是我们用6中基础模式就能描绘出一副图像。以下就是25种不同的卷积核的示例:

总结:卷积层的通过卷积核的过滤提取出图片中局部的特征,跟上面提到的人类视觉的特征提取类似。

1. 数学原理

卷积操作原理上其实是对两个矩阵进行点乘求和的数学操作,其中一个矩阵为输入的数据矩阵,另一个矩阵则为卷积核(滤波器或特征矩阵),求得的结果表示为原始图像中提取的特定局部特征。

2. 卷积的作用

在图像领域中,深层卷积已经证明比浅层卷积更具表征,从图像的特征提取来看, 不同卷积操作提取到的特征类型是不相同的:

卷积层次 特征类型
浅层卷积 边缘特征
中层卷积 局部特征
深层卷积 全局特征

3. 一些常见的卷积核

在传统图像领域,已经证明一些特殊的卷积核能够执行边缘检测,锐化,模糊等操作, 如下表所示:

卷积作用 卷积核 卷积后图像
输出原图 origin_img
边缘检测(突出边缘差异) edgeDetect-1
边缘检测(突出中间值) edgeDetect-2
图像锐化 sharpen_img
方块模糊 box_blur
高斯模糊 gaussian_blur

4. 卷积核的参数

参数名 作用 常见设置
Kernel Size 卷积核的大小 在过去常设为5,如LeNet-5;现在多设为3,通过堆叠的卷积核来达到更大的感受域
Stride 卷积步长 常见设置为1,表示滑窗距离为1,可以覆盖所有相邻位置特征的组合;当设置为更大值时相当于对特征组合降采样
Padding 填充策略 SAME: 表示对不足卷积核大小的边界位置进行某种填充(通常零填充)以保证卷积输出维度与与输入维度一致;VALID时则对不足卷积尺寸的部分进行舍弃,输出维度就无法保证与输入维度一致
In Channels 卷积核的深度 默认与输入的特征矩阵通道数(深度)一致;在某些压缩模型中会采用通道分离的卷积方式
Out Channels 卷积核的个数 若设置为与输入通道数一样的大小,可以保持输入输出维度的一致性;若采用比输入通道数更小的值,则可以减少整体网络的参数量

5. 几种常见的卷积方式

https://zhuanlan.zhihu.com/p/28186857

6. 从 pytorch 看一维卷积,二维卷积,三维卷积

参数说明

卷积操作常用的有一维卷积,二维卷积与三维卷积,其中,三维卷积用到就比较少了, 三个类在 Pytorch 中的参数都是一样的,只是输入输出维度有所差别罢了。

1
2
3
4
5
6
7
8
9
in_channels: 输入数据的通道数
out_channels: 卷积操作产生的输出通道数
kernels: 卷积核的大小, int 或 tuple, 卷积核的大小设置是需要反复实验测试的。
stride: 卷积步伐,stride 太小,会导致重复计算较多,计算量大; 而太大,有可能会造成特征遗漏。
padding: 输入数据的每一条边填充0的层数, int 或 tuple, 默认为0
padding_mode: 填充方式, zeros: 以0为填充数据
dilation: 卷积核中元素之间的间距, 默认为 1
groups: 从输入通道到输出通道的阻塞连接数, 默认为1
bias: 是否添加 bias, 默认为True

一维卷积

1
2
3
4
5
6
7
8
9
class torch.nn.Conv1d:

-- 输入输出数据:
Input: [N, C_in, L_in]: [batch_size, in_channels, input_len]
Output: [N, C_out, L_out]: [batch_size, out_channels, output_len]

-- 参数:
权重参数: [out_channels, in_channels/groups, kernel_size], 默认初始化为均匀分布
Bias参数: [out_channels], 默认初始化为均匀分布

一维卷积在NLP中常用于 Embedding 部分来提取特征,如在TextCNN中就有使用, 此时可以将词向量维度理解为通道数C_in, 输入序列的长度为 L_in

注意一点的是,在一维卷积中,卷积核的大小是一维的, 即如 果指定为 n, 则卷积核的大小为 [n, 1, 1]

二维卷积

2dconv

  • 单通道:若输入卷积核尺寸为 ,卷积核在输入图像的空间维度上进行滑窗操作,每次滑窗和 窗口内的值进行卷积操作,得到输出图像中的一个值。
  • 多通道:输入图像特征通道数为3,卷积核尺寸为 ,每次滑窗与3个通道上的 窗口内的所有值进行卷积操作,得到输出图像中的一个值。
1
2
3
4
5
6
7
8
9
class torch.nn.Conv2d:

-- 输入输出数据:
Input: [N, C_in, H_in, L_in]: [batch_size, in_channels, input_len]
Output: [N, C_out, H_out, L_out]: [batch_size, out_channels, output_len]

-- 参数:
权重参数: [out_channels, in_channels/groups, kernel_size], 默认初始化为均匀分布
Bias参数: [out_channels], 默认初始化为均匀分布

三维卷积

3dconv

7. 卷积核的选择

大卷积核虽然可以获取更大的感受域,但是大卷积核反而会导致计算量大幅增加,不利于训练更深层的模型,相应的计算能力也会降低。

堆叠2个 3×3 卷积核(二通道)可以获得与 5×5卷积核 相同的感受视野,同时参数量会更少(3×3×2+1<5×5×1+1),这也是 3×3卷积 应用更广泛的原因,在大多数情况下通过堆叠较小的卷积核比直接采用单个更大的卷积核会更加有效。

激活层

激活层本质就是采用激活函数对卷积出的特征做一个非线性变换。

  • 首选 Relu, 然后试试 Relu 变体 Leaky Relu 和 Maxout。
  • 某些情况下 tanh 也能获得不错结果。

池化层(下采样) 数据降维,避免过拟合

池化层简单说就是下采样,他可以大大降低数据的维度。其过程如下:

上图中,我们可以看到,原始图片是20×20的,我们对其进行下采样,采样窗口为10×10,最终将其下采样成为一个2×2大小的特征图。

之所以这么做的原因,是因为即使做完了卷积,图像仍然很大(因为卷积核比较小),所以为了降低数据维度,就进行下采样。

总结:池化层相比卷积层可以更有效的降低数据维度,这么做不但可以大大减少运算量,还可以有效的避免过拟合。

数学原理

池化层的作用是对感受域内的特征进行筛选,提取区域内最具代表性的特征,能够有效地降低特征尺度,进而减少模型所需要的参数量,此外还可以防止过拟合现象。

池化操作的本质是降采样。其除了能显著降低参数数量外,还能保持对平移,伸缩,旋转操作的不变性。

  • 常见的池化操作:选择指导 (Boureau et al., 2010)

    • 最大池化: Max Pooling
    • 平均值池化: Mean Pooling

无论max pooling还是mean pooling,都没有需要学习的参数。因此,在卷积神经网络的训练中,Pooling层需要做的仅仅是将误差层传递到上一层,而没有梯度的计算。

对于max Pooling,下一层的误差项的值会原封不动的传递到上一层对应区块中的最大值所对应的神经元,而其他神经元的误差项都是0。

对于 mean Pooling, 下一层的误差项会均匀划分到该层的所有的神经元上。

卷积层与池化层比较

卷积层 池化层
结构 零填充时输出维度不变,而通道数改变 通常特征维度会降低,通道数不变
稳定性 输入特征发生细微改变时,输出结果会改变 感受域内的细微变化不影响输出结果
作用 感受域内提取局部关联特征 感受域内提取泛化特征,降低维度
参数量 与卷积核尺寸、卷积核个数相关 不引入额外参数

全连接层 — 输出结果

这个部分就是最后一步了,经过卷积层和池化层处理过的数据输入到全连接层,得到最终想要的结果。

经过卷积层和池化层降维过的数据,全连接层才能”跑得动”,不然数据量太大,计算成本高,效率低下。

典型的 CNN 并非只是上面提到的3层结构,而是多层结构,例如 LeNet-5 的结构就如下图所示:

卷积层 – 池化层- 卷积层 – 池化层 – 卷积层 – 全连接层

在了解了 CNN 的基本原理后,我们重点说一下 CNN 的实际应用有哪些。

NLP 与 CV 中使用 CNN 的区别

NLP CV
卷积核 多为一维卷积, 通常都是由较为浅层的卷积层组成 对二维信号做卷积,一般设为叠加的3×3卷积核
Pooling 一般采用 Max-Pooling
全连接层 一般常采用LN + dropout 一般常采用BN + dropout

CNN 的实际应用

  • 图片分类、检索
  • 目标定位检测
  • 目标分割
  • 人脸识别
  • 骨骼识别

QA

1. 为什么需要 Padding ?

图像是 5 × 5的矩阵,我们的卷积核是 3 × 3的,最终我们得出的feature map是 3 × 3 的矩阵(n -f + 1) 。

这样会带来两个问题:

  • 每一次做卷积操作时,你的图像就会缩小,如果这种情况发生多次,你的图像就会变得很小。

  • 边缘的像素点所受到的关注点比中心的关注点少很多。比如上图的 1 * 1 的像素点只进行了一次卷积计算,而中心点 3 * 3 却进行了9次卷积计算,这明显是不公平的。这意味着图像边缘的信息大多都丢失了。

如果加上 paddding 之后,我们的 feature-map 就变为 (n + 2p - f + 1) × (n + 2p - f + 1)的矩阵。

Padding存在的意义在于:

  • 为了不丢弃原图信息

  • 为了保持feature map 的大小与原图一致

  • 为了让更深层的layer的 input 依旧保持有足够大的信息量

  • 为了实现上述目的,且不做多余的事情,padding出来的pixel的值都是0,不存在噪音问题。

2. 为什么卷积核设计尺寸都是奇数

  • 保证像素点中心位置,避免位置信息偏移
  • 填充边缘时能保证两边都能填充,原矩阵依然对称

3. 卷积操作的特点

  • **稀疏交互:**卷积神经网络中,卷积核尺度远小于输入的尺度,这样每个输出神经网仅与前一层区域内的神经元存在连接权重,我们称此为稀疏交互。

    • 提高了模型的统计效率:原本一幅图像只能提供少量特征,现在每一块像素区域都可以提供一部分特征
    • 使得参数大量减少,优化的时间复杂度也会减小几个数量级,过拟合情况也得到改善。
    • 稀疏交互的意义在于,先从局部的特征入手,再将局部特征组合起来形成更复杂和抽象的特征
  • 参数共享: 参数共享指的是同一个模型的不同模块中使用相同的参数。参数共享的意义在于使得卷积层具有平移等特性

    • 权重共享一定程度上能增强参数之间的联系,获得更好的共性特征
    • 很大程度上降低了网络的参数,节省计算量和计算所需内存
    • 权重共享能起到很好正则的作用。正则化的目的是为了降低模型复杂度,防止过拟合,而权重共享则正好降低了模型的参数和复杂度。
  • 平移不变性:(局部)平移不变性是一个很有用的性质,尤其是当我们关心某个特征是否出现而不关心它出现的具体位置时。平移不变性是由于参数共享 和池化 所带来的。

4. 你觉得 CNN 有什么不足?

  • 信息损失问题。 CNN在Pooling的时候会丢失大量的有价值信息,以及忽略局部与整体之间的关联性比如得分最高的特征只出现了一次,而得分第二高的特征出现了很多次,得分第二高的特征可能比最高的特征还要重要,却被丢弃了,自然造成了不小的信息损失

  • 忽略了位置信息:一个区域有用的特征极有可能和另一个区域的信息有联系,如TextCNN:对于一些粒度较粗的分类问题如话题分类,位置信息可能不大,但对于如情感分析这种粒度较细的分类问题,位置信息不足便会导致一些问题,如”虽然他长的很帅,但是人品不好”和”虽然他人品不好,但他长得帅啊”,在情感倾向上区别还是比较明显的。

5. CNN 与 RNN 的优劣

  • 并行能力, 训练时间很漫长
  • RNN 容易发生梯度消失,包括 LSTM
  • CNN 的感受视野受限于卷积核,需要深层的 CNN 网络来获得更大的感受视野

6. 卷积,池化的意义

  • 卷积和池化可能导致欠拟合
    • 如果一项任务涉及到要对输入中相隔较远的信息进行合并时,那么卷积可能就不正确了。
    • 如果一项任务依赖于保存精确的空间信息,那么在所有的特征上使用池化将会增大训练误差。
  • 当我们比较卷积模型的统计学习表现时,只能以基准中的其他卷积模型作为比较的对象

7. 卷积中不同零填充的影响

假定 m, k 分别代表图像的宽度和卷积核的宽度:

  • Valid 卷积(有效卷积):不使用零填充,卷积核只允许访问那些图像中能够完全包含整个核的位置,输出的宽度为 m − k + 1
    • 在这种情况下,输出的所有像素都是输入中相同数量像素的函数,这使得输出像素的表示更加规范。
    • 然而,输出的大小在每一层都会缩减,这限制了网络中能够包含的卷积层的层数。(一般情况下,影响不大,除非是上百层的网络)
  • Same 卷积(相同卷积):只进行足够的零填充来保持输出和输入具有相同的大小,即输出的宽度为 m.
    • 在这种情况下,只要硬件支持,网络就能包含任意多的卷积层。
    • 然而,输入像素中靠近边界的部分相比于中间部分对于输出像素的影响更小。这可能会导致边界像素存在一定程度的欠表示。
  • **Full 卷积(全卷积):**进行足够多的零填充使得每个像素都能被访问 k 次(非全卷积只有中间的像素能被访问 k 次),最终输出图像的宽度为 m + k − 1
    • 因为 same 卷积可能导致边界像素欠表示,从而出现了 Full 卷积;
    • 但是在这种情况下,输出像素中靠近边界的部分相比于中间部分是更少像素的函数。这将导致学得的卷积核不能再所有所有位置表现一致
    • 事实上,很少使用 Full 卷积

通常零填充的最优数量处于 “有效卷积”和 “相同卷积” 之间。

8. 1 * 1 卷积的作用?

https://zhuanlan.zhihu.com/p/40050371

  • 实现信息的跨通道交互和整合。
  • 对卷积核通道数进行降维和升维,减小参数量。

9. 卷积核是否越大越好?

卷积核越大,参数量越多。 前期无法使用较小卷积核是因为,前期的模型无法做的很深,这样限制了卷积核的感受视野。但其实,通过堆叠2 个 3 * 3 卷积核可以获得与 5 * 5 卷积核相同的感受视野,同时参数量特更少。 因此,大多数情况下,通过堆叠较小的卷积核比直接采用单个较大的卷积核更加有效。

自然语言中, TextCNN 就采用单层的卷积核,此时选择合适的,较大的卷积核相对比较重要, 而DPCNN 中,因为能够将卷积做的很深,那么就可以采用3 * 3 的卷积核来做了。

10. 如何减少卷积层参数量?

  • 用深层小卷积代替浅层大卷积
  • 使用分离卷积操作:将原本的卷积操作分离为的两部分操作
  • 添加 卷积
  • 在卷积层前使用池化操作

11. CNN 特点

  • 区域不变性: filter 在每层的输入向量(图像)上滑动,检测的是局部信息,然后通过pooling取最大值或均值。pooling这步综合了局部特征,失去了每个特征的位置信息。

    这很适合基于图像的任务,比如要判断一幅图里有没有猫这种生物,你可能不会去关心这只猫出现在图像的哪个区域。但是在NLP里,词语在句子或是段落里出现的位置,顺序,都是很重要的信息。

  • 局部组合性: CNN中,每个滤波器都把较低层的局部特征组合生成较高层的更全局化的特征。

    这在CV里很好理解,像素组合成边缘,边缘生成形状,最后把各种形状组合起来得到复杂的物体表达。在语言里,当然也有类似的组合关系,但是远不如图像来的直接。而且在图像里,相邻像素必须是相关的,相邻的词语却未必相关。

12. 为何较大的batch size 能够提高 CNN 的泛化能力?

在相同迭代次数和学习率的条件下,每批次采用更多的数据将有助于模型更好的学习到正确的模式,模型输出结果也会更加稳定

13. SAME 与 VALID 的区别

  • SAME: 宽卷积,通常采用零填充的方式对卷积核不满足整除条件的输入特征进行补全,以使卷积层的输出维度保持与输入特征维度一致。
  • VALID:窄卷积,不进行任何填充,在输入特征边缘位置若不足以进行卷积操作,则对边缘信息进行舍弃,因此在步长为1的情况下该填充方式的卷积层输出特征维度可能会略小于输入特征的维度。

14. CNN 优缺点

优点:

  • 共享卷积核,优化计算量。
  • 无需手动选取特征,训练好权重,即得特征。
  • 深层次的网络抽取图像信息丰富,表达效果好。
  • 保持了层级网络结构。
  • 不同层次有不同形式与功能。

缺点:

  • 需要调参,需要大样本量,GPU等硬件依赖。
  • 物理含义不明确。

基本单元 MLP

deep-learning

感知机

1. 万能近似定理

一个前馈神经网络如果具有至少一个非线性输出层,那么只要给予网络足够数量的隐藏单元,它就可以以任意的精度来近似任何从一个有限维空间到另一个有限维空间的函数。

万能近似定理表明一个单层的网络就足以表达任意函数,但是该层的维数可能非常大,且几乎没有泛化能力;此时,使用更深的模型能够减少所需的单元数,同时增强泛化能力(减少泛化误差)。参数数量相同的情况下,浅层网络比深层网络更容易过拟合。

2.在深度神经网络中,非线性单元,放弃了训练问题的凸性,其意义何在?

放弃训练问题的凸性,简单来说,就是放弃寻求问题的最优解。

非线性单元的加入,使训练问题不再是一个凸优化问题。这意味着神经网络很难得到最优解,即使一个只有两层和三个节点的简单神经网络,其训练优化问题仍然是 NP-hard 问题 (Blum & Rivest, 1993).

但即使如此,使用神经网络也是利大于弊的:

  • 人类设计者只需要寻找正确的函数族即可,而不需要去寻找精确的函数。
  • 使用简单的梯度下降优化方法就可以高效地找到足够好的局部最小值
  • 增强了模型的学习/拟合能力,如原书中所说“ maxout 单元可以以任意精度近似任何凸函数”。至于放弃凸性后的优化问题可以在结合工程实践来不断改进。 “似乎传统的优化理论结果是残酷的,但我们可以通过工程方法数学技巧来尽量规避这些问题,例如启发式方法、增加更多的机器和使用新的硬件(如GPU)。”

3. 如何解决非线性问题

  • 手动去设计一个非线性转换
  • 核方法:其实内部本质也是非线性变换
  • 神经网络:依据激活函数来提供非线性

循环神经网络 RNN

卷积神经网络 – CNN 和普通的算法大部分都是输入和输出的一一对应,也就是一个输入得到一个输出。不同的输入之间是没有联系的

但是在某些场景中,一个输入就不够了!

为了填好下面的空,取前面任何一个词都不合适,我们不但需要知道前面所有的词,还需要知道词之间的顺序。

这种需要处理「序列数据 – 一串相互依赖的数据流」的场景就需要使用 RNN 来解决了。

典型的集中序列数据:

  1. 文章里的文字内容
  2. 语音里的音频内容
  3. 股票市场中的价格走势
  4. ……

RNN 之所以能够有效的处理序列数据,主要是基于他的比较特殊的运行原理。下面给大家介绍一下 RNN 的基本运行原理。

原理

传统神经网络的结构比较简单:输入层 – 隐藏层 – 输出层。如下图所示:

RNN 跟传统神经网络最大的区别在于每次都会将前一次的输出结果,带到下一次的隐藏层中,一起训练。如下图所示:

下面用一个具体的案例来看看 RNN 是如何工作的:

假如需要判断用户的说话意图(问天气、问时间、设置闹钟…),用户说了一句“what time is it?”我们需要先对这句话进行分词:

然后按照顺序输入 RNN ,我们先将 “what”作为 RNN 的输入,得到输出「01」

然后,我们按照顺序,将“time”输入到 RNN 网络,得到输出「02」。

这个过程我们可以看到,输入 “time” 的时候,前面 “what” 的输出也产生了影响(隐藏层中有一半是黑色的)。

以此类推,前面所有的输入都对未来的输出产生了影响,大家可以看到圆形隐藏层中包含了前面所有的颜色。如下图所示:

当我们判断意图的时候,只需要最后一层的输出「05」,如下图所示:

RNN 的缺点也比较明显

通过上面的例子,我们已经发现,短期的记忆影响较大(如橙色区域),但是长期的记忆影响就很小(如黑色和绿色区域),这就是 RNN 存在的短期记忆问题。

  1. RNN 有短期记忆问题,无法处理很长的输入序列
  2. 训练 RNN 需要投入极大的成本

由于 RNN 的短期记忆问题,后来又出现了基于 RNN 的优化算法,下面给大家简单介绍一下。

RNN 的优化算法 LSTM

RNN 是一种死板的逻辑,越晚的输入影响越大,越早的输入影响越小,且无法改变这个逻辑。

LSTM 做的最大的改变就是打破了这个死板的逻辑,而改用了一套灵活了逻辑——只保留重要的信息。

简单说就是:抓重点!

举个例子,我们先快速的阅读下面这段话:

当我们快速阅读完之后,可能只会记住下面几个重点:

LSTM 类似上面的划重点,**他可以保留较长序列数据中的「重要信息」,忽略不重要的信息。**这样就解决了 RNN 短期记忆的问题。

从 LSTM 到 GRU

Gated Recurrent Unit – GRU 是 LSTM 的一个变体。他保留了 LSTM 划重点,遗忘不重要信息的特点,在long-term 传播的时候也不会被丢失。

GRU 主要是在 LSTM 的模型上做了一些简化和调整,在训练数据集比较大的情况下可以节省很多时间。

RNN 的应用和使用场景

只要涉及到序列数据的处理问题,都可以使用到,NLP 就是一个典型的应用场景。

文本生成: 类似上面的填空题,给出前后文,然后预测空格中的词是什么。

机器翻译: 翻译工作也是典型的序列问题,词的顺序直接影响了翻译的结果。

语音识别: 根据输入音频判断对应的文字是什么。

生成图像描述: 类似看图说话,给一张图,能够描述出图片中的内容。这个往往是 RNN 和 CNN 的结合。

视频标记: 他将视频分解为图片,然后用图像描述来描述图片内容。

总结

RNN的独特价值在于:它能有效的处理序列数据。比如:文章内容、语音音频、股票价格走势…

之所以他能处理序列数据,是因为在序列中前面的输入也会影响到后面的输出,相当于有了“记忆功能”。但是 RNN 存在严重的短期记忆问题,长期的数据影响很小(哪怕他是重要的信息)。

于是基于 RNN 出现了 LSTM 和 GRU 等变种算法。这些变种算法主要有几个特点:

  1. 长期信息可以有效的保留
  2. 挑选重要信息保留,不重要的信息会选择“遗忘”

RNN 几个典型的应用如下:

  • 文本生成
  • 语音识别
  • 机器翻译
  • 生成图像描述
  • 视频标记

基础相关


QA

1. RNN 中为何会出现梯度消失,梯度爆炸问题

RNN 的梯度消失问题

因此, RNN 的梯度消失,梯度爆炸问题在于:

2. Relu 能否作为RNN的激活函数

答案是可以,但会产生一些问题:

  • 换成 Relu 可能使得输出值变得特别大,从而产生溢出
  • 换成Relu 也不能解决梯度消失,梯度爆炸问题,因为还有 连乘的存在(如1中公式)

为什么 CNN 和前馈神经网络采用Relu 就能解决梯度消失,梯度爆炸问题?

因为CNN 或 FNN 中各层的 W 并不相同, 且初始化时是独立同分布的,一定程度熵可以抵消。

而 RNN 中各层矩阵 是一样的。

3. 推导 LSTM

关键在于三个门, 三个状态。 其中三个门的公式基本一样

  • 遗忘门: 决定上一时刻的 多少保留到当前时刻
  • 输入门:决定当前时刻输入 有多少保存到当前时刻

  • 输出门:控制当前时刻的 有多少信息作为当前时刻的 :

  • 当前输入的状态 : 将上一时刻的 与当前时刻的 融合:

  • 当前时刻的状态 : 将 , 融合:

  • 当前时刻的输出 :从 中分出一部分信息:

4. LSTM 长短记忆机制

长短记忆机制主要通过 输入门遗忘门 来实现:

  • 如果当前信息不重要, 则输入门相应维度接近于 0, 当前的信息就几乎不融入进入 。反之, 输入门相应维度接近于 1, 当前信息实现很好的融入。
  • 如果之前的信息 不重要,则遗忘门相应维度接近于 0, 过去的信息就几乎不融入进 。 反之,亦然。

5. LSTM的门机制为何选择 sigmoid 作为激活函数?

值得一提的是, 目前几乎所有主流的门控机制中,门控单元的选择均使用 sigmoid 。

  • sigmoid 的饱和性: 十分符合 门控 的效果
  • 值域在 (0,1), 当输入较大或较小时,输出会接近1 或 0, 从而保证门的开或关。

6. 融合信息时为何选择 tanh?

  • 值域为 (-1, 1), 这样会带来两个好处:

    • 与大多数情景下特征分布以 0 为中心相吻合。(激活函数一章中有提到这点特性的重要性)
    • 可以避免前向传播时的数值溢出问题(主要是上溢)
  • tanh 在 0 附近有较大的梯度,模型收敛更快

7. 计算资源有限的情况下有没有什么优化方法?

  • 采用 Hard gate
  • 采用 GRU

8. 推导一下 GRU

两个门,两个状态

  • 更新门:控制前一时刻状态信息与当前输入融合

  • 重置门:控制前一时刻状态信息

  • 当前输入的信息融入

  • 当前时刻的状态:

9. LSTM 与 GRU 之间的关系

  • GRU 认为遗忘门输入门功能有一定的的重合,认为之前的信息 与 当前的输入信息是此消彼长的关系,因此将二者合并成一个门: 更新门。
  • 合并了记忆状态 c 与隐藏状态 h
  • 采用重置门代替了输出门

10 为何RNN 会有梯度消失现象,推一下?

RNN 的梯度消失问题

11. LSTM 与 GRU 区别

  • LSTM 中的单元状态 c 与 GRU 中的 h 类似,但 GRU 去掉了 h 这个状态,即最后的输出不再进行调节,那么也就不需要输出门了
  • 在产生新的全局状态时, LSTM 采用 输入门+遗忘门 的方式, 而 GRU 只采用更新门来控制
  • 更新门起到了遗忘门的作用, 重置门起到了输入门的作用。

12. 为何 RNN 训练时 loss 波动很大

由于RNN特有的memory会影响后期其他的RNN的特点,梯度时大时小,learning rate没法个性化的调整,导致RNN在train的过程中,Loss会震荡起伏。

为了解决RNN的这个问题,在训练的时候,可以设置临界值,当梯度大于某个临界值,直接截断,用这个临界值作为梯度的大小,防止大幅震荡。

13. LSTM 中的激活函数选择

LSTM, 门的激活函数选择 Sigmoid, 而在生成 c 时采用 tanh。

  • Sigmoid函数的输出在0~1之间,符合门控的物理定义。且当输入较大或较小时,其输出会非常接近1或0,从而保证该门开或关。
  • 在生成候选记忆时,使用Tanh函数,是因为其输出在−1~1之间,这与大多数场景下特征分布是0中心的吻合。此外,Tanh函数在输入为0附近相比Sigmoid函数有更大的梯度,通常使模型收敛更快。

长短期记忆网络 LSTM

原理

长短期记忆网络——通常被称为 (Long-Short Term Memory,LSTM),是一种特殊的 RNN,能够学习长期依赖性。由 Hochreiter 和 Schmidhuber(1997)提出的,并且在接下来的工作中被许多人改进和推广。LSTM 在各种各样的问题上表现非常出色,现在被广泛使用。

LSTM 被明确设计用来避免长期依赖性问题。长时间记住信息实际上是 LSTM 的默认行为,而不是需要努力学习的东西!

所有递归神经网络都具有神经网络的链式重复模块。在标准的 RNN 中,这个重复模块具有非常简单的结构,例如只有单个 tanh 层。

LSTM 也具有这种类似的链式结构,但重复模块具有不同的结构。不是一个单独的神经网络层,而是四个,并且以非常特殊的方式进行交互。

不要担心细节。稍后我们将逐步浏览 LSTM 的图解。现在,让我们试着去熟悉我们将使用的符号。

在上面的图中,每行包含一个完整的向量,从一个节点的输出到其他节点的输入。粉色圆圈表示逐点运算,如向量加法;而黄色框表示学习的神经网络层。行合并表示串联,而分支表示其内容正在被复制,并且副本将转到不同的位置。

核心思路

LSTM 的关键是细胞状态,即图中上方的水平线。

细胞状态有点像传送带。它贯穿整个链条,只有一些次要的线性交互作用。信息很容易以不变的方式流过。

LSTM 可以通过所谓“门”的精细结构向细胞状态添加或移除信息。

门可以选择性地以让信息通过。它们由 S 形神经网络层和逐点乘法运算组成。

S 形网络的输出值介于 0 和 1 之间,表示有多大比例的信息通过。0 值表示“没有信息通过”,1 值表示“所有信息通过”。

一个 LSTM 有三种这样的门用来保持和控制细胞状态。

基础理论 AUC计算

基础理论 Softmax

1. Softmax 定义

2. Softmax 损失


QA

1. 为何一般选择 softmax 为多分类的输出层

虽然能够将输出范围概率限制在 [0,1]之间的方法有很多,但 Softmax 的好处在于, 它使得输出两极化:正样本的结果趋近于 1, 负样本的结果趋近于 0。 可以说, Softmax 是 logistic 的一种泛化。

基础理论 偏差 vs 方差,欠拟合 vs 过拟合

参考: 偏差与方差, 欠拟合与过拟合

定义

  • 记在训练集 D 上学得的模型为

    模型的期望预测

  • 偏差(Bias)

    偏差度量了学习算法的期望预测真实结果的偏离程度,即刻画了学习算法本身的拟合能力;

  • 方差(Variance)

    方差度量了同样大小的训练集的变动所导致的学习性能的变化,即刻画了数据扰动所造成的影响(模型的稳定性);

  • 噪声则表达了在当前任务上任何学习算法所能达到的期望泛化误差的下界,即刻画了学习问题本身的难度。

  • 偏差-方差分解”表明模型的泛化能力是由算法的能力、数据的充分性、任务本身的难度共同决定的。

理解概念

  • 偏差: 表示模型在训练集上的表现,与训练误差成线性关系, 用于描述模型的拟合能力
  • 方差: 表示模型在(开发集或测试集)与测试误差-训练误差成线性关系,用于描述模型的泛化能力。

四种情况

  1. 偏差很低,方差很高: 意味着训练误差很低,测试误差很高,此时发生了过拟合现象。
  2. 偏差很高,方差很低: 意味着训练误差,测试误差都很高,此时发生了欠拟合现在。
  3. 偏差,方差都很高: 意味着此时同时发生了欠拟合和过拟合现象。
  4. 偏差很低,方差很低: 意味着训练误差很低,测试误差也很低,表示我们的模型训练的结果很好。

偏差与欠拟合,方差与过拟合

  • 偏差通常是由于我们定义的模型不合适或模型复杂度不够,所造成的现象为欠拟合。
  • 方差主要是由于模型复杂度过高造成的, 所造成的现象是过拟合。

如何降低偏差(欠拟合)

  1. 加大模型规模(更换其余机器学习算法,神经网络可以增加每层神经元/神经网络层数):

    偏差很高很有可能是因为模型的拟合能力差,对于传统机器学习算法,各个方法的拟合能力不同,选择一个拟合能力更好的算法往往能够得出很好的结果。 对于神经网络(拟合能力最强)而言,通过增加网络层数或增加每层单元数就能够很好的提高模型的拟合能力[3][4][5]。

  2. 根据误差分析结果来修改特征:

    我们需要将错误样本分类,判断可能是由于什么原因导致样本失败,在针对分析结果,增加或减少一些特征。

  3. 减少或去除正则化: 这可以避免偏差,但会增大方差。

  4. 修改模型结构,以适应你的问题:对于不同的问题,不同的模型结构会产生更好的结果,比如在CV中常用CNN,而在NLP领域常用LSTM。

如何降低方差(过拟合)

  1. 重新分析,清洗数据。

    有时候,造成方差很大的原因往往是由于数据不良造成的,对于深度学习来说,有一个大规模,高质量的数据集是极为重要的。

  2. 添加更多的训练数据。

    增大训练数据能够往往能够提高模型的泛化能力。可以采用数据增强技术。

  3. 加入正则化。

  4. 加入提前终止。

    意思就是在训练误差变化很慢甚至不变的时候可以停止训练,这项技术可以降低方差,但有可能增大了偏差。 提前终止有助于我们能够在到达最佳拟合附近,避免进入过拟合状态。

  5. 通过特征选择减少输入特征的数量和种类。

    显著减少特征数量能够提高模型的泛化能力,但模型的拟合能力会降低,这意味着,该技术可以减小方差,但可能会增大偏差。 不过在深度学习中,我们往往直接将所有特征放入神经网络中,交给算法来选择取舍。

  6. 减少模型规模,降低模型复杂度(每层神经元个数/神经网络层数): 谨慎使用。

    一般情况下,对于复杂问题如CV或NLP等问题不会降低模型复杂度,而对于简单问题,采用简单模型往往训练速度更快,效果很好。

  7. 根据误差分析结果修改输入特征。

  8. 修改模型架构,使之更适合你的问题。 一般可以选择简单模型的情况下,不选择复杂模型。

  9. 集成学习。

基础理论 分类问题评估指标

几个定义:混淆矩阵

  • TP: True Positives, 表示实际为正例且被分类器判定为正例的样本数
  • FP: False Positives, 表示实际为负例且被分类器判定为正例的样本数
  • FN: False Negatives, 表示实际为正例但被分类器判定为负例的样本数
  • TN: True Negatives, 表示实际为负例且被分类器判定为负例的样本数

一个小技巧, 第一个字母表示划分正确与否, T 表示判定正确(判定正确), F表示判定错误(False); 第二个字母表示分类器判定结果, P表示判定为正例, N表示判定为负例。

几个常规的指标

Accuracy:

Accuracy 能够清晰的判断我们模型的表现,但有一个严重的缺陷: 在正负样本不均衡的情况下,占比大的类别往往会成为影响 Accuracy 的最主要因素,此时的 Accuracy 并不能很好的反映模型的整体情况。

Precision:

Recall:

Precision 与 Recall 的权衡

精确率高,意味着分类器要尽量在 “更有把握” 的情况下才将样本预测为正样本, 这意味着精确率能够很好的体现模型对于负样本的区分能力,精确率越高,则模型对负样本区分能力越强。

召回率高,意味着分类器尽可能将有可能为正样本的样本预测为正样本,这意味着召回率能够很好的体现模型对于正样本的区分能力,召回率越高,则模型对正样本的区分能力越强。

从上面的分析可以看出,精确率与召回率是此消彼长的关系, 如果分类器只把可能性大的样本预测为正样本,那么会漏掉很多可能性相对不大但依旧满足的正样本,从而导致召回率降低。

F1 Score

F1-Score 能够很好的评估模型,其主要用于二分类问题, 计算如下:

而 更一般的有

其实, 本质上是Recall, Precision 权重比, 当 时, 表明 Recall 的权重要比Precision高,其影响更大, ; 当 时, 表明 Recall 的权重要比Precision低, 对应的影响更小;

前面提到 F1 针对的是二分类,而更一般的是,对于多分类问题来说, F1 的计算有多种方式,可以参见 Scikit-Learn 中的评价指标,我们来分别介绍一下。

对于一个多分类问题,假设,对于分类 而言有:, 那么各种 F1 的值计算如下。

Macro F1: 宏平均

Macro 算法在计算 Precision 与 Recall 时是先分别计算每个类别的Precision 与 Recall, 然后再进行平均。

那么我们就得到最终的 Macro F1 的计算为:

我们看到, Macro F1 本质上是所有类别的统计指标的算术平均值来求得的,这样单纯的平均忽略了样本之间分布可能存在极大不平衡的情况

Micro F1 :微平均

Micro 算法在计算 Precision 与 Recall 时会将所有类直接放到一起来计算。

Macro vs Micro [1]

Macro 相对 Micro 而言,小类别起到的作用更大,举个例子而言,对于一个四分类问题有:

  • class A: 1 TP, 1 FP
  • class B: 10 TP , 90 FP
  • class C: 1 TP, 1 FP
  • class D: 1 TP, 1 FP

那么对于 Precision 的计算有:

我们看到,对于 Macro 来说, 小类别相当程度上拉高了 Precision 的值,而实际上, 并没有那么多样本被正确分类,考虑到实际的环境中,真实样本分布和训练样本分布相同的情况下,这种指标明显是有问题的, 小类别起到的作用太大,以至于大样本的分类情况不佳。 而对于 Micro 来说,其考虑到了这种样本不均衡的问题, 因此在这种情况下相对较佳。

总的来说, 如果你的类别比较均衡,则随便; 如果你认为大样本的类别应该占据更重要的位置, 使用Micro; 如果你认为小样本也应该占据重要的位置,则使用 Macro; 如果 Micro << Macro , 则意味着在大样本类别中出现了严重的分类错误; 如果 Macro << Micro , 则意味着小样本类别中出现了严重的分类错误。

为了解决 Macro 无法衡量样本均衡问题,一个很好的方法是求加权的 Macro, 因此 Weighed F1 出现了。

Weight F1

Weighted 算法算术 Macro 算法的改良版,是为了解决Macro中没有考虑样本不均衡的原因, 在计算 Precision与Recall 时候,各个类别的 Precision 与 Recall要乘以该类在总样本中的占比来求和:

那么我们就得到最终的 Macro F1 的计算为:

MCC :马修斯相关系数

MCC 主要用于衡量二分类问题,其综合考虑了 TP TN, FP , FN, 是一个比较均衡的指标, 对于样本不均衡情况下也可以使用。MCC的取值范围在 [-1, 1], 取值为1 表示预测与实际完全一致, 取值为0表示预测的结果还不如随机预测的结果, -1 表示预测结果与实际的结果完全不一致。因此我们看到, MCC 本质上描述了预测结果与实际结果之间的相关系数。

值得注意的是,对于两个分类器而言,可能其中一个分类器的 F1 值较高,而其 MCC 值较低, 这表示单一的指标是无法衡量分类器的所有优点与缺点的。

ROC 曲线

在分类任务中,测试部分通常是获得一个概率表示当前样本属于正例的概率, 我们往往会采取一个阈值,大于该阈值的为正例, 小于该阈值的为负例。 如果我们减小这个阈值, 那么会有更多的样本被识别为正类,这会提高正类的识别率,但同时会降低负类的识别率。

为了形象的描述上述的这种变化, 引入ROC曲线来评价一个分类器的好坏。 ROC 曲线主要关注两个指标:

其中, FPR 代表将负例错分为正例的概率, TPR 表示能将正例分对的概率, 如果我们增大阈值, 则 TPR 会增加,而对应的FPR也会增大, 而绘制ROC曲线能够帮助我们找到二者的均衡点,下图很清晰的描述了ROC 曲线关系:

在 ROC 曲线中, 有:

  • FPR = 0, TPR = 0: 表示将每一个实例都预测为负类
  • FPR = 1, TPR = 1:表示将每一个实例都预测为正例
  • FPR = 0, TPR = 1:为最优分类点
  • 分类器对应的ROC曲线应该尽可能靠近坐标轴的左上角, 而对角线的位置意味着分类器的效果和随机猜测一样的差。

**ROC曲线在测试集中的样本分布发生变化的时候能够保持不变。**但遗憾的是,很多时候, ROC 曲线并不能清晰的说明哪个分类器的效果更好, 而 AUC 恰恰能够对分类器做出直观的评价。

AUC:Area under Curve

AUC 为ROC 曲线下的面积, 这个面积的数值介于0到1之间, 能够直观的评价出分类器的好坏, AUC的值越大, 分类器效果越好。

  • AUC = 1: 完美分类器, 采用该模型,不管设定什么阈值都能得出完美预测(绝大多数时候不存在)
  • 0.5 < AUC < 1: 优于随机猜测,分类器好好设定阈值的话,有预测价值
  • AUC = 0.5: 跟随机猜测一样,模型没有预测价值
  • AUC < 0.5 :比随机猜测还差,但是如果反着预测,就优于随机猜测。

值得一提的是,两个模型的AUC 相等并不代表模型的效果相同, 比如这样:

实际场景中, AUC 的确是非常常用的一种指标。

需要注意的是, 在多分类场景下的 ROC 曲线以及 AUC 值, 此时 ROC 曲线应该有多个, 而AUC 的计算如下:

P-R 曲线

P-R 曲线其横坐标为 Recall, 纵坐标为 Precision, 其能帮助我们很好的做出权衡

在上图中,我们发现, A 完全包住了C, 着意味着A 的Precision 与 Recall 都高于C, A优于C。 而对比 A,B, 二者存在交叉的情况,此时采用曲线下面积大小衡量性能,面积越大,性能越好,此处的A优于B。

最后

对于最终分类指标的选择, 在不同数据集,不同场景,不同时间下都会有不同的选择,但往往最好选出一个指标来做优化,对于二分类问题,我目前用 AUC 比较多一些, 多分类我还是看 F1 值。

Reference

[1] Should I make decisions based on micro-averaged or macro-averaged evaluation measures?

[2] Micro Average vs Macro average Performance in a Multiclass classification setting>

[3 机器学习性能评估指标

QA

1. 训练集中类别不平衡,哪个参数最不准确?

Accuracy

基础理论 指数加权平均

指数加权平均本质上是一种近似求取平均值的方法。

我们也以吴恩达课上的例子举例, 假设

  • 表示从第0天到第 天的平均温度值。
  • 表示第 t 点的温度值。

我们具体展开来说, 假设时间 ,加权参数 , 那么则有:

我们将上式带入化简有:

观察上式我们发现, 指数加权平均实质上就是以指数式加权递减的移动平均。 各数值的加权而随时间而指数式递减,越近期的数据加权越重,但较旧的数据也给予一定的加权。

但有一点需要注意的是, 我们观察上式,在最后一项中它的系数为 , 这个数已经很接近于0了, 这就意味着,在 时刻对加权平均值所起到的作用微乎其微, 继而引出一个问题: 我们加权平均所得到的值到底平均了多少天?

答案是 天。这是因为当 时, 有 , 当 时, 有 , 也就是说当权重下降到 (或者说) 以下时就被忽略不计了。

前面说到指数平均的本质依旧是计算平均值,那么在深度学习中为什么不使用我们常用的平均值求法,而要搞得这么复杂呢? 答案是效率以及内存问题。

在深度学习中,数据量经常是非常庞大的, 如果我们使用传统方法来计算平均值,无论是从内存还是从计算量上, 对计算机的压力是很大的, 而对比对数加权平均方法, 我们每次只需要保存上一时刻的值,无论是内存开销还是计算量都小的可怜。

偏差修正

当我们还有指数加权平均来计算平均值时, 一开始的指数加权平均值会很小, 不能代表平均值, 所以需要使用偏差修正:

但是一般机器学习并不关心一开始的指数加权平均值,所以可以不用偏差修正来修正。

基础理论 数据角度看深度学习

数据集定义

  • 训练集: 训练集用来训练你的模型,来确定模型的参数而非超参数,这些参数往往称为学习参数, 如权重参数W, 偏置参数b。
  • **验证集:**交叉验证集用于验证模型的performance,从而对模型进行超参数调整以及确定最终模型,这些超参数包括:学习率,网络结构等 。有时也称为交叉验证集。
  • **测试集:**测试集用于对算法进行评估,不会改变学习算法和参数。

数据集划分

划分原则

  • 验证集的规模应该尽可能大,至少能够区分出你所尝试的不同算法之间的性能差异。一般来说,验证集的规模应该在 1000 - 10000 之间。
  • 测试集的规模应该大到使你能够对模型的性能进行一个高度可信的评估即可。当数据规模一般时(100-10000)时,采用数据的10%-30%来作为测试集;在数据规模很大时(10w级别),采用1%作为1%甚至更小。总的来说,只要能够很好的评估模型性能即可。
  • 验证集与测试集的规模并不是越大越好,但如果数据丰富,可以适当选择较大的验证集与测试集。

划分建议

  • 在样本量有限的情况下,有时候会把验证集和测试集合并。实际中,若划分为三类,那么训练集:验证集:测试集=6:2:2;若是两类,则训练集:验证集=7:3。
  • 在海量样本的情况下,这种情况在目前深度学习中会比较常见。此时由于数据量巨大,我们不需要将过多的数据用于验证和测试集。例如拥有1百万样本时,我们按训练集:验证集:测试集=98:1:1的比例划分,1%的验证和1%的测试集都已经拥有了1万个样本,这已足够验证模型性能了。

数据时分布

  • 训练集的分布不需要与实际数据分布一致,而应该更多的考虑如何均衡样本分布。

  • 验证集与测试集应该服从同一分布,且该分布能够很好的反应实际数据的分布。二者分布相同有助于定位问题:

    • 如果模型在验证集上表现良好,却在测试集上表现不佳,那么问题可以定位为:算法在验证集上过拟合了

    • 如果二者分布不同时,发生此情况,问题就有很多了如:

      • 算法在验证集上过拟合了。
      • 测试集比验证集更难进行预测,尽管算法做得足够好了,却很难有进一步的提升空间。
      • 测试集不一定更难预测,但它与开发集性质并不相同(分布不同)。
  • 训练集分布于验证集,测试集分布没必要一致。训练集更多的考虑模型的performance,而测试集与验证集是与真实数据相关的,更多考虑的是泛化能力。

数据不匹配问题

1 如何定位数据不匹配?

​ 数据不匹配问题是个不容易定位和解决的问题。这个问题出现总会和模型过拟合表现很相似,即在训练集上能体现非常不错的性能,但在测试集上表现总是差强人意但区别在于如果遇到是数据不匹配的问题,通常在用一批和训
练集有看相同或者相似分布的数据上仍然能取得不错的结果。但很多时候,当测试集上结果表现很差时,很多初学
者可能会直接将问题定位在模型过拟合上,最后对模型尝试各种方法后,性能却始终不能得到有效提升。当遇到这
种情况时,建议先定位出是否存在数据不匹配的问题。最简单的验证方式就是可以从训练集中挑选出一部分数据作
为验证集,重新划分后训练和验证模型表现。

2 举例常见几个数据不匹配的场景?

​ 例如设计款识别物体的app时,实际场景的图片均来自于手机拍摄,而训练集确是来自于网上各类抓取下来的图
片。例如在图像去噪、去模糊、去雾、超分辨率等图像处理场景时,由于大量数据的难以获取,因此都会采用人为
假设合成的图像进行训练,这时候应用到实际场景中也容易出现不匹配的问题

3 如何解决数据不匹配问题?

数据不匹配是个很难有固定方法来解决的问题。这里提供几条供参考的途径:
​ 1、收集更多符合实际场最需要的数据。这似乎是最简单但也最难方式
​ 2、对结果做错误分析。找出数据集中出错的数据和正确数据之间的特点和区别,这对你无论是进行后续模型的分析或者是数据的处理提供非常有效的思路。注意,这里的数据集包括训练集和测试集
​ 3、数据集增强。数据集增强并不意味看数据集越大越好,其目的是丰富数据的分布以适应更多的变化当遇到数
据不匹配时,对数据处理般可以有两种方式。其一,合成或处理更多接近需要的数据特点。其二,对所有数据包
括实际场景数据都进行处理,将所有数据都统一到另一个分布上,统一出一种新的特点。

4 如何提高深度学习系统的性能

当我们要试图提高深度学习系统的性能时,目前我们大致可以从三方面考虑:

​ 1、提高模型的结构,比如增加神经网络的层数,或者将简单的神经元单位换成复杂的 LSTM 神经元,比如在自然语言处理领域内,利用 LSTM 模型挖掘语法分析的优势。

​ 2、改进模型的初始化方式,保证早期梯度具有某些有益的性质,或者具备大量的稀疏性,或者利用线性代数原理的优势。

​ 3、选择更强大的学习算法,比如对度梯度更新的方式,也可以是采用除以先前梯度 L2 范数来更新所有参数,甚至还可以选用计算代价较大的二阶算法。


QA

1. 数据为何要 shuffle ?

shuffle 的意思是洗牌或弄乱,即打乱数据集中样本的排列顺序。这样带来一个直接的好处就是样本的分布变得均匀了。

在优化中有一个原则是:网络从意料之外的样本中学习最快,所以说,如果为了加速学习,我们要求每次喂入的数据和前一份数据相关性较低。

总的来说,shuffle的意义在于加速模型学习。

基础理论 梯度消失,梯度爆炸问题

1. 梯度消失,梯度爆炸产生原因

请看我的这篇文章: RNN 的梯度消失问题, 讲的已经很清楚了。

总的来说,梯度消失,梯度爆炸问题本质上是由于随着深度的加深,受到权重信息,激活函数的影响,连乘机制所引发的一系列问题。

2. 解决方案

解决梯度消失,梯度爆炸问题,最终的目的是解决如何在深层网络上的优化问题,当然深层网络所带来的问题远不止梯度消失,爆炸问题。

1. 采用 Relu 系激活函数

参考:激活函数

2. 合适的权重初始化

参考:权重初始化

3. 残差结构

残差的方式,能使得深层的网络梯度通过跳级连接路径直接返回到浅层部分,使得网络无论多深都能将梯度进行有效的回传。

4. Batch Normalization, Layer Normalization

参考:Normalization

5. LSTM

参考:RNN 的梯度消失问题, 讲的很清楚了。

6. 梯度裁剪 - 梯度爆炸

如果梯度超过某个阈值,就对其进行限制。

基础理论 目标函数,损失函数,代价函数

经验风险与结构风险

  • 经验风险指的是模型对数据的拟合程度,拟合程度越高,经验风险越小。(其实对应的就是代价函数)
  • 结构风险指的是对模型复杂度的评估,模型越复杂,结构风险越大。(其实对应的就是目标函数)

只考虑将经验风险最小化,会出现过拟合现象。

损失函数,代价函数,目标函数

其实在很多论文和博客中都用的很随意,其实三者之间是有着细微的区别的:

  • 损失函数(Loss Function):一般针对单个样本的描述。其用来衡量模型预测值与真实值不一致的程度,是一个非负实值函数,通常使用 表示。 损失函数越小,模型的鲁棒性就越好。

  • 代价函数(Cost Function):一般是针对总体。我们需要通过训练代价函数来获得最优参数,最常见的如平方差代价函数:

  • 目标函数(Object Function):等价于 代价函数 + 正则化项, 其往往也是我们模型中要优化求解的函数 – 目标函数。

常用的损失函数

1 . 0-1 损失函数

相等为 0 , 不相等为1。一般的在实际使用中,相等的条件过于严格,可适当放宽条件:

2. 绝对值损失函数

3. 平方损失函数

4. 对数损失函数

常见的逻辑回归使用的就是对数损失函数。逻辑回归它假设样本服从伯努利分布(0-1分布),进而求得满足该分布的似然函数,接着取对数求极值等

5. 指数损失函数

指数损失函数的标准形式为:

例如AdaBoost就是以指数损失函数为损失函数。

6. Hinge损失函数

其中 是预测值,范围为 为目标值,其为

线性支持向量机中,最优化问题可等价于

上式相似于下式

其中是Hinge损失函数,可看做为正则化项。

常用的代价函数

二次代价函数适合输出神经元是线性的情况,交叉熵代价函数适合输出神经元是S型函数的情况。

1. 二次代价函数

2. 交叉熵代价函数

  • 它是⾮负的, J > 0。可以看出:式子中的求和中的所有独⽴的项都是负数的,因为对数函数的定义域是 (0,1),并且求和前⾯有⼀个负号,所以结果是非负。
  • 如果对于所有的训练输⼊ x,神经元实际的输出接近⽬标值,那么交叉熵将接近 0。

3. 对数似然函数代价函数

交叉熵一般与 sigmoid 结合,而对数似然代价函数一般与 softmax 结合。 对数似然代价函数在二分类时可以化简为交叉熵代价函数的形式。

QA

1. Sigmoid 为何与交叉熵搭配二不用二次方代价函数

如果使用二次方代价函数,根据权值 的偏导:

考虑到 sigmoid 函数倒数在输出接近 0 和 1 时非常小, 会导致一些样本在刚开始训练时学习的非常慢。

2. sigmoid 为何要与交叉熵搭配

交叉熵函数权值和偏置的梯度推导为:

由以上公式可知,权重学习的速度受到影响,更大的误差,就有更快的学习速度,避免了二次代价函数方程中因导致的学习缓慢的情况。

3. Logistic 回归为何要使用对数损失函数?

逻辑回归它假设样本服从伯努利分布(0-1分布),进而求得满足该分布的似然函数,接着取对数求极值等。整个过程如下:

  • Logistic 回归模型为:

  • Logistic 回归的概率分布为伯努利分布,其概率函数为:

  • 其似然函数为:

  • 对应的对数似然函数为:

将对数似然函数与上文提到的对数损失函数对比,发现,二者的本质是相同的,所以Logistic 直接采用对数损失函数。

4.为什么交叉熵损失相比均方误差损失能提高以 sigmoid 和 softmax 作为激活函数的层的性能?

简单来说,就是使用均方误差(MSE)作为损失函数时,会导致大部分情况下梯度偏小,其结果就是权重的更新很慢,且容易造成“梯度消失”现象。而交叉熵损失克服了这个缺点,当误差大的时候,权重更新就快,当误差小的时候,权重的更新才慢。

推导过程: https://blog.csdn.net/guoyunfei20/article/details/78247263

5. 损失函数有哪些? 怎么用?

  • 平方损失 – 预测问题
  • 交叉熵 – 分类问题
  • Hinge 损失 – SVM
  • CART 回归树的残差损失

Reference

[1] DeepLearning-500-questions

基础理论 维数灾难问题

引言

先思考一个问题: 数据的维度越高越好吗? 恐怕不是吧,不然为什么机器学习中特征工程如此的重要,简单来说, 当数据维度过高时,会为学习带来一些困难。

其实,任何的机器学习算法,其性能与特征数量的关系往往是这样的:

1

1. 维度再难会带来哪些问题?

  • 数据稀疏: 这很好理解, 因为维数增多,样本密度必然减少, 举例而言:假设我们现在有10个样本, 而每一维的宽度为5个单位, 这样样本密度为 ; 那么在二维空间下, 样本密度为: , 我们看到样本密度成倍数减少,最终造成了数据稀疏。

  • **样本分布不均匀:**准确的来说,处于中心位置的训练样本比边缘训练样本更加稀疏。

    这点可以通过数学定理来解释:N个点在p维单位球内随机分布,则随着p的增大,这些点会越来越远离单位球的中心,转而往外缘分散。而各点距单位球中心距离的计算公式为:

    从另一个角度来看,对于D维空间,位于半径 和半径 之间的部分占球总体积的百分比是多少?

    答案是,随着D的增加,这个比率接近为1 , 这也就解释了为什么在高维空间中,球体的大部分体积都聚集在表面附近的薄球壳上。

  • **过拟合问题:**可以肯定的一点是,样本在高维数据上更容易分类,但是,在高维中训练得到的分类器其实相当于低维空间上的一个复杂非线性分类器,而了解过拟合的同学都应该知道, 模型过于复杂往往是造成过拟合的直接原因。

2. 如何解决维数灾难问题?

  • 对于数据稀疏与分布不均的问题,只有通过增加训练样本和降维的方式来解决。
  • 对于过拟合问题,可以添加针对过拟合的一些操作来解决。

基础理论 距离度量方法

1. 欧式距离

衡量点之间的直线距离

2. 曼哈顿距离

3. 余弦距离

将两个点看做是空间中的两个向量,通过衡量两向量之间的相似性来衡量样本之间的相似性。

4. 切比雪夫距离

各对应坐标数值差的最大值。


QA

1. 余弦相似度 与 欧式距离的区别与联系

  • 区别:

    欧式距离和余弦相似度都能度量2个向量之间的相似度,但是欧式距离从2点之间的距离去考量,余弦相似从2个向量之间的夹角去考量。举例如下:

    假设 2人对三部电影的评分分别是 A = [3, 3, 3]B = [5, 5, 5]

    那么2人的欧式距离是 根号12 = 3.46, A、B的余弦相似度是1(方向完全一致)。

    从上例可以发出,2人对三部电影的评价趋势是一致的,但是欧式距离并不能反映出这一点,余弦相似则能够很好地反应。余弦相似可以很好地规避指标刻度的差异,最常见的应用是计算 文本的相似度

  • 联系:

    归一化后计算的欧式距离是关于余弦相似的单调函数,可以认为归一化后,余弦相似与欧式距离效果是一致的(欧式距离越小等价于余弦相似度越大)。

    因此可以将 求余弦相似转为求欧式距离 ,余弦相似的计算复杂度过高,转为求欧式距离后,可以借助KDTree(KNN算法用到)或者BallTree(对高维向量友好)来降低复杂度。

1.cosine

基础理论 迁移学习

基础理论 局部最小值,鞍点

基础原理

神经网络最终收敛何处?

QA


1. 如何避免陷入局部最小值与鞍点?

  • SGD 或 Mini-batch:SGD 与 Mini-batch 引入了随机性,每次以部分样本来计算梯度,能够相当程度上避免陷入局部最小值。
  • 动量: 引入动量,相当于引入惯性。一些常见情况时,如上次梯度过大,导致进入局部最小点时,下一次更新能很容易借助上次的大梯度跳出局部最小点。
  • 自适应学习率:通过学习率来控制梯度是一个很棒的思想, 自适应学习率算法能够基于历史的累计梯度去计算一个当前较优的学习率。

多任务学习

浅谈多任务学习(Multi-task Learning): https://zhuanlan.zhihu.com/p/348873723

Refernence

An Overview of Multi-Task Learning in Deep Neural Networks

对比学习

Reference

对比学习(Contrastive Learning)综述

对比学习(Contrastive Learning)相关进展梳理

损失函数

Focal loss

深度学习模型压缩 综述

https://zhuanlan.zhihu.com/p/67871864

https://zhuanlan.zhihu.com/p/36051603

https://blog.csdn.net/wspba/article/details/75671573

自监督学习

https://zhuanlan.zhihu.com/p/110278826

https://zhuanlan.zhihu.com/p/125721565

调参 优化算法

优化算法在深度学习中也是十分重要的,虽然一般情况下无脑 Adam 即可,但有时采用其余的优化算法反而能够获得更好的结果,这点很有意思。同时,理解优化算法的原理对于选择和面试还是很有帮助的。

超参数设置 – 遵循原论文

优化算法 超参数
SGD
Momentum
Adagrad
RMSprop/ Adadelta
Adam
Adamax
Nadam

三大基本算法

1. 随机梯度下降

2. 标准梯度下降

3. mini-batch 梯度下降

三者比较

  • 随机梯度下降: 每次更新的方向并不向全局最优解的方向前进,最终的收敛结果也往往在全局最优解附近,但并不能达到最优解。迭代过程不可测。不容易陷入局部最小值。
  • 标准梯度下降: 更新速度很慢,每次都要计算全部样本的梯度。且由于梯度方向过于稳定一致(没有随机因素)且更新次数过少,很容易陷入鞍点或局部最小值。
  • mini-batch 梯度下降: 二者折中,batch size 的设置是一个艺术。

梯度下降算法的一点改进

1. 动量梯度下降法

在使用梯度下降算法中,很容易产生一种“震荡现象”(相邻前后梯度正负相反),这种震荡现象减慢了梯度下降法的速度,这也导致你无法使用更大的学习率, 如果你使用较大的学习率, 可能导致震荡更大, 收敛更慢。

**Momentum的核心思想: 通过计算梯度的指数加权平均值,并利用该平均值来更新你的权重,这样梯度的变化就没有那么快了。**其本质是通过增加动量来减少随机,增加梯度的稳定性。

举个例子, 假如这里有个碗状的峡谷, 峡谷中坑坑洼洼,有许多小坡, 如果我们从峡谷上推下一个球, 根据物理现象,由于加速度,小球的速度在下降的过程中越来越快, 即使路上遇到小坡,也能够轻松跨越(跨不过去,就是局部最小点了), 直至到达谷底。

引申到动量法的参数变化中: 对于在梯度点处具有相同的方向的维度,表明加速度为正,那么速度自然加快;对于在梯度点处改变方向的维度, 加速度为负, 速度减缓。 这样,我们可以得到更快的收敛速度, 同时可以减少摇摆。

2. Nesterov Accelerated Gradient

momentum

  • 思想: 在动量法中, 小球总是以一种盲目的方式滚动, 这会造成一个问题, 在临近最优点的附近时控制不住速度,于是会造成我们在最优点附近摇啊摇,最终收敛。

    我们希望小球足够聪明,它能够预判后面的地形, 如果后面是下坡路就加速下降, 如果后面是上坡路,说明我们已经到了最优点附近, 该减速了。

  • 实现方式:Nesterov就利用这一思想,它将 假定为下一位置, 通过计算它的梯度,就可以得到我们接下来是加速还是刹车了,的确很聪明。

  • 优点:Nesterov Accelerated Gradient 相比Momentum, 能显著的提升了优化效果,收敛速度要快很多。

我们来从数学角度分析一下, 相对 momentum, 到底发生了什么变化:

具体推论需要再次参考 比Momentum更快:揭开Nesterov Accelerated Gradient的真面目

自适应学习率优化算法

0. 为何要自适应学习率?

在梯度下降的过程中,每个参数更新的频率与幅度是不同的,到了训练中后期,对于某些变量,也许已经到达了极小值附近,而有些变量仍然在初始位置不远处。 此时,如果我们采用不同的学习率会导致一个问题: 如果学习率偏小,则那些更新不多的参数会收敛的很慢,如果学习率偏大,那么对于处于极小值附近的参数,很容易产生不稳定现象。

为了解决这个问题,我们需要针对不同的参数设置不同的学习率, 但参数是无穷尽的, 不可能去人为的设置每一个参数的学习率,因此,自适应学习率就显得很有必要了。

1. Adagrad

  • 是一个对角矩阵, 上的元素表示在第 t 步更新时, 历史上 梯度的积累。
  • **思想:**对每个参数用不同的学习率,这个学习率在一开始比较大,用于快速梯度下降。随着优化过程的进行,对于已经下降很多的参数,则减缓学习率,对于还没怎么下降的参数,则保持一个较大的学习率。

  • 方法: 通过维护一个对角矩阵来累积历史梯度来实现学习率的变化, 其中对角线上的每个元素表示某个参数历史梯度的累积。

    如果某参数历史梯度较大,那么说明该参数优化的快,更有可能到达最优点附近, 而此时它在对角矩阵上对应的累积梯度也大, 从而使得对应的学习率较小,最终实现不同参数有着不同的学习率。

  • 优点: 十分适合处理稀疏数据。消除了需要手动调整学习率的问题。

  • 缺陷: 分母项的积累: 由于每个附加项都是正数,因此累积总和在训练期间不断增长。这反过来导致学习速率缩小并最终变得无限小,此时算法不再进行优化。

2. Adadelta

  • 表示 t 时刻的**平方梯度对数平均值**, 本质的思想用了对数平均的思路。
  • 改进: 改进 Adagrad 中学习率最终无限小的问题。
  • 思想: 通过设定一个窗口大小 w , 来求最近 w 个平方梯度的对数平均值(对数平均的思想),采用求平均值而非求和的方式可以有效的避免学习率无限低问题。

3. RMSprop

比较 RMSprop 与 Adadelta 二者公式可以发现,在 Adadelta 取 就是RMSprop了。

4. Adam

  • 是**历史梯度**的**对数平均估计**, 是**历史梯度平方**的**对数平均估计**,其实就是求取的 的近似。
  • 是对 的校正,可以近似为对 的无偏估计。

我们结合 Momentum 与 RMSProp 算法来看, Adam算法本质上就是将二者结合,同时考虑到梯度与梯度平方, 通过历史梯度来加速收敛, 通过历史梯度平方来修正学习率。

  • 优点: 高效的计算,收敛非常快。适合解决大规模数据和参数优化问题。

  • 为何要进行偏差修正:

    因为初始化的 为 0 向量,在通过指数平均计算均值时会偏差向 0, 尤其是在初始时间步中和 非常小的情况下(接近于1),尤其如此。

更复杂的分析,推荐: 深度学习最常用的算法:Adam优化算法

5. AdaMax

6. Nadam

如何选择优化算法?

我个人一般选择 Adam, 优点是,收敛快,这样模型迭代起来也快, 如果是轻量级模型的话, 需要好好选择优化算法调参, 而如果是重量级的模型, 无脑 Adam 是一个相当不错的选择。

QA

1. 在mini-batch 中, batch size 会带来怎样的影响?

batch size 的大小往往是由多个因素决定的:

  • 较大的批能得到更精确的梯度估计
  • 较小的批能带来更好的泛化误差,泛化误差通常在批大小为 1 时最好。但是,因为梯度估计的高方差,小批量训练时需要较小的学习率以保持稳定性,这意味着更长的训练时间
  • batch size 与所需显存息息相关,可参见:GPU 显存不足怎么办?
  • 在 GPU 上, 请采用 2 的幂数作为 batch size, 一般取值在 32 - 256。
  • 小批量更容易利用多核架构,但是太小的批并不会减少计算时间,这促使我们使用一些绝对最小批量

2. 深度学习为什么不用二阶优化?

目前深度学习中,反向传播主要是依靠一阶梯度。二阶梯度在理论和实际上都是可以应用都网络中的,但相比于一阶梯度,二阶优化会存在以下一些主要问题:

  • 计算量大,训练非常慢。
  • 二阶方法能够更快地求得更高精度的解,这在浅层模型是有益的。而在神经网络这类深层模型中对参数的精度要求不高,甚至不高的精度对模型还有益处,能够提高模型的泛化能力。
  • 稳定性:二阶方法能更快求高精度的解,同样对数据本身要的精度也会相应的变高,这就会导致稳定性上的问题。

Reference

[1] An overview of gradient descent optimization algorithms

路遥知马力——Momentum

比Momentum更快:揭开Nesterov Accelerated Gradient的真面目

调参 权重初始化

前言

本节先对一些常见的初始化方案进行描述,然后依托于 Pytorch , 论述 Pytorch 中提供的几个初始化方案,最后提出一些使用建议。

权重初始化为何如此重要?

虽然 Batch Normalization, Layer Normalization 等 Trick 大大减轻了我们需要精选权重初始化方案的需要,但对于大多数情况下, 选择合适的初始化方案依旧有利于加速我们模型的收敛。

从根本上看,选择合适的初始化方案能够使得我们的损失函数便于优化(有些优化面坑坑洼洼,有些优化面比较光滑); 从另一个角度来说, 合适的权重初始化有利于减轻梯度消失,梯度爆炸问题(参考公式推导)。

Xavier 初始化

  • 目的: 减轻梯度消失问题。

在对梯度的研究中, 发现反向梯度从输出层到输入层逐渐减小, 同时反向梯度的方差随网络反向也逐渐减小,针对这种现象,提出了Xavier initialization。

其的基本思想为:保持每一层输入的方差,反向梯度的方差一致。通过方差可以控制输入输出分布以及分布密度之间不要相差太大, 这可以使得信息在网络中能够更平滑的传播。

Kaiming 初始化

kaiming初始化的出现是因为xavier存在一个不成立的假设。xavier在推导中假设激活函数都是线性的,而在深度学习中常用的ReLu等都是非线性的激活函数。而kaiming初始化本质上是高斯分布初始化,与上述高斯分布初始化有所不同,其是个满足均值为0,方差为2/n的高斯分布:

  • n 为所在曾的输入维度

初始化方案

1. 常量初始化

  • 初始化为 0: 当我们在初始化的时候,最容易想到的就是初始化为0,但是,将W初始化为0, 那么在前向计算的时候,我们的所有神经元的输出均为相同, 然后在反向传播中, 梯度相同权重更新相同,这明显是不可行的。

    所以, 千万不要初始化为0。

1
torch.nn.init.constant_(tensor, val)

2. 随机初始化

如果我们采用随机初始化,因为我们不知道我们的参数会初始化为多少, 如果初始化不合理, 造成梯度消失的可能性是相当之大,另一方面,如果初始化在优化面坑坑洼洼的那一面,我们的优化过程将变得异常曲折,局部最小值,鞍点以及大的平坦区会造成优化的噩梦。

2. 均匀分布初始化 - U(a,b)

1
torch.nn.init.uniform_(tensor, a=0.0, b=1.0)

3. 高斯分布 - N(mean, std)

1
torch.nn.init.normal_(tensor, mean=0.0, std=1.0)

4. 单位矩阵初始化

1
torch.nn.init.eye_(tensor)

5. Xavier 初始化

  • Xavier 均匀分布

    1
    torch.nn.init.xavier_uniform_(tensor, gain=1.0)
  • Xavier 正态分布

    1
    torch.nn.init.xavier_normal_(tensor, gain=1.0)

6. Kaiming 初始化(MSRA初始化)

  • Kaiming 均匀分布

    1
    torch.nn.init.kaiming_uniform_(tensor, a=0, mode='fan_in', nonlinearity='leaky_relu')
  • Kaiming 正态分布

    1
    torch.nn.init.kaiming_normal_(tensor, a=0, mode='fan_in', nonlinearity='leaky_relu')

7. 正交初始化

1
torch.nn.init.orthogonal_(tensor, gain=1)

8. 稀疏初始化

1
torch.nn.init.sparse_(tensor, sparsity, std=0.01)

QA

1. 推导一下 Xavier 的过程

单层网络

假设我们使用线性激活函数 ,那么对于一层网络来说有:

根据方差展开式有:

那么,当 时, 输出 y 的方差为:

如果 独立同分布, 也独立同分布, 那么有:

那么,我们就可以得出:

于是,为了保证方差的一致性,则应该有:

现在我们延伸到多层网络中,我们假设 是第 层激活函数的输出向量, 是第 层激活函数的输入向量。

前向传播

那么在前向传播中, 第 层的方差可以累积表达为:

反向传播

而在反向传播公式中, 损失函数对于 梯度公式为:

那么在d层网络中,第 层梯度的累计方差为:

我们的目的是,要求各层输入方差一致且各层梯度的方差也一致,这也就意味着:

那么必须有:

我们的W需要同时满足以上两个条件, 因此作为折中,有:

如果我们假设 W 服从均匀分布,则W在区间[a,b]内均匀分布的方差为:

那么带入就可以得到W的分布:

适用范围

Reference

[1] Xavier Glorot et al., Understanding the Difficult of Training Deep Feedforward Neural Networks

[2] Kaiming He et al., Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classfication

聊一聊深度学习的weight initialization

吴恩达团队:神经网络如何正确初始化?

调参 激活函数

https://zhuanlan.zhihu.com/p/352668984

前言

本文先对激活函数的特性,常见的激活函数以及如何选择合适的激活函数。

**需要注意的是,激活函数是来向神经网络中引入非线性因素的,通过激活函数,神经网络就可以拟合各种曲线。**可参考:激活函数,你真的懂了吗?

激活函数的性质

  • **非线性:**为模型引入非线性因素

  • **几乎处处可微:**有限的不可微点有左右导数(左右导数可能不同,如Relu)。 便于反向传播,利于优化

  • **计算简单:**激活函数在神经网络前向的计算次数与神经元的个数成正比,因此简单的非线性函数自然更适合用作激活函数。这也是ReLU之流比其它使用Exp等操作的激活函数更受欢迎的其中一个原因。

  • **非饱和性:**饱和指的是在某些区间梯度接近于零(即梯度消失),使得参数无法继续更新的问题。

  • **单调性:**当激活函数是单调的时候,单层网络能够保证是凸函数;

  • : 当激活函数满足这个性质的时候,如果参数的初始化是随机的较小值,那么神经网络的训练将会很高效;如果不满足这个性质,那么就需要详细地去设置初始值。

    由于这个条件与非线性有点矛盾,因此激活函数基本只是部分满足这个条件,如 relu 只再 x>0 时为线性。

  • 输出值的范围有限: 当激活函数输出值是有限的时候,基于梯度的优化方法会更加稳定,因为特征的表示受有限权值的影响更显著;但这导致了前面提到的梯度消失问题,而且强行让每一层的输出限制到固定范围会限制其表达能力。

    当激活函数的输出是无限的时候,模型的训练会更加高效,不过在这种情况小,一般需要更小的 Learning Rate。

  • 参数少: 大部分激活函数都是没有参数的。

  • 归一化: 主要思想是使样本分布自动归一化到零均值、单位方差的分布,从而稳定训练。

激活函数一览

1. sigmoid

2. tanh

tanh 本质上是 sigmoid 向下平移和伸缩后的结果。

3. Relu

如何选择激活函数

  • 如果是二分类问题, 输出层是sigmoid,其余层是Relu
  • 一般隐层采用Relu, 有时也要试试 tanh, 这两大函数的变体都有必要试试

Relu 的优点

  • Relu 不耗费资源,且导数为1, 学习起来较快
  • sigmoid, tanh 的导数在正负饱和区的梯度都会接近于0, 这会造成梯度消失。
  • Relu 有Dead Relu 问题,此时试试其变体, 如Leaky Relu

激活函数的稀疏激活性

从信号方面来看,即神经元同时只对输入信号的少部分选择性响应,大量信号被刻意的屏蔽了,这样可以提高学习的精度,更好更快地提取稀疏特征。当 时,ReLU 硬饱和,而当 时,则不存在饱和问题。ReLU 能够在 时保持梯度不衰减,从而缓解梯度消失问题。

QA

0. Dead Relu 问题

某些神经元可能永远不会被激活, 导致其相应的参数永远不能被更新。其本质是由于Relu在的小于0时其梯度为0所导致的。

首先我们假设Relu的输入是一个低方差中心在+0.1的正态分布, 此时假设现在大多数Relu的输入是正数,那么大多数输入经过Relu函数能得到一个正值, 因此此时大多数输入能够反向传播通过Relu得到一个梯度, 于是我们的Relu的输入就完成了更新。

假设在随机反向传播中, 有一个巨大的梯度经过了Relu且此时Relu的输入为正(Relu是打开的), 那么该梯度会引起Relu输入X的巨大变化, 假设此时输入X的分布变成了一个中心在-0.1 的正态分布。此时的情况如下:

首先, 大多数Relu的输入变为负数, 输入经过Relu函数就能得到一个0, 这也意味着大多数输入不能反向传播通过Relu得到一个梯度,导致这部分输入无法通过更新。

1. Relu VS Sigmoid VS tanh

  • sigmoid 缺陷:

    • 极容易导致梯度消失问题
    • 计算费时
    • sigmoid 函数不是关于原点中心对称的
  • tanh 缺陷: 无法解决梯度消失问题

  • Relu 优点:

    • 一定程度上缓解了梯度问题: 其导数始终为一个常数
    • 计算速度非常快: 求导不涉及浮点运算,所以速度更快
    • 减缓过拟合: ReLU 在负半区的输出为 0。一旦神经元的激活值进入负半区,那么该激活值就不会产生梯度/不会被训练,造成了网络的稀疏性——稀疏激活, 这有助于减少参数的相互依赖,缓解过拟合问题的发生

2. 为什么Relu 不是全程可微也能用于基于梯度的学习?

虽然 ReLU 在 0 点不可导,但是它依然存在左导数和右导数,只是它们不相等(相等的话就可导了),于是在实现时通常会返回左导数或右导数的其中一个,而不是报告一个导数不存在的错误。

3. 为何加入非线性因素能够加强网络的表示能力?

  • 神经网络的万能近似定理:神经网络只要具有至少一个非线性隐藏层,那么只要给予网络足够数量的隐藏单元,它就可以以任意的精度来近似任何从一个有限维空间到另一个有限维空间的函数。
  • 如果不使用非线性激活函数,那么每一层输出都是上层输入的线性组合;此时无论网络有多少层,其整体也将是线性的,这会导致失去万能近似的性质
  • 但仅部分层是纯线性是可以接受的,这有助于减少网络中的参数

4. 为何 tanh 比 sigmoid 收敛快?

调参 超参数调优

https://zhuanlan.zhihu.com/p/29247151

超参数一览

1. 超参数是什么?

  • 参数: 需要训练,指的是模型训练中的权重参数和 bias 参数。
  • 超参数: 不需要训练,需要在训练前进行指定,并不断调整。

其实就很多超参数来说,调整的意义并不大,毕竟往往网络的超参数多达几十个,要是都精调的话,那岂不是得 gg, 因此往往是对重要参数精调,对次要参数粗调。

此外,很多 Trick 往往需要一些其他的超参数,对于这部分参数,往往我会遵循原论文,适当的调一调就行。毕竟,Trick 无穷尽呀。

2. 网络结构参数

网络参数指的是你自己构建网络结构时的相关参数,如卷积核数量,网络层数等

  • CNN 网络参数

    超参数 说明 推荐值
    kernel size 卷积核的 size 一般为奇数:[7 * 7], [5 * 5], [3 * 3], [1 * 1]
    kernel num 卷积核的数量 一般在 [100, 600] 间探索
  • RNN 网络参数

    超参数 说明 推荐值
  • Transformer 参数

    超参数 说明 推荐值

2. 优化参数

优化参数指的是反向传播中所涉及到的参数,主要包括:学习率, batch_size, 对应优化器参数, 损失函数参数等。

  • 常见参数
超参数 说明 推荐值
learning rate 最重要的参数,需要精调 下文有推荐
batch size 次要重要参数,需要精调 [1: 1024]
dropout 解决过拟合的重要参数,需要精调 [0: 0.5]
  • 优化器相关参数:

    优化器 参数说明 推荐值
    Adam
  • 正则化参数:

    超参 说明 推荐值
    L2 权重衰减系数 [0, 1e-4]

3. Trick 参数

超参数 说明 推荐值

几个重要的超参数

1. 学习率 – 最重要的超参数

学习率直接控制着梯度更新时的量级,从而直接影响模型的优化与最终的有效容量。 幸运的是,对于学习率的设置,已经有一套行之可效的指导方案了, 针对不同的优化器,有不同的设置区间。

如果是微调,那么学习率要降低两个数量级左右(参考 Bert 的 adam 学习率)

优化器 设置范围
SGD [1e-2 ,1e-1]
Momentum [1e-3, 1e-2]
Adagrad [1e-3, 1e-2]
Adadelta [1e-2, 1e-1]
RMSprop [1e-3, 1e-2]
Adam [1e-3, 1e-2]
Nadam [1e-3, 1e-2]

2. batch size

一般情况下, batch size 我往往会以 128 为起点,上下调整,注意,batch size 要设置为 2 的幂次方, 范围在 [1, 1024] 之间。

此外,需要一提的是 Batch Normalization 与 batch size 息息相关,如果你使用了 Batch Normalization, 那么 batch size 就不能设的太小, 这点我在 Normalization 那一节中有详细解释。

3. dropout

dropout 我往往会设置先为 0.5, 然后在 [0.0, 0.5] 范围内精调。

Dropout 往往会在卷积层和全连接层之间是有来防止过拟合。 使用 Dropout 需要注意两点:

  • 在RNN中,如果直接放在memory cell中,循环会放大噪声,扰乱学习。一般会建议放在输入和输出层;
  • 不建议dropout后直接跟上batchnorm,dropout很可能影响batchnorm计算统计量,导致方差偏移,这种情况下会使得推理阶段出现模型完全垮掉的极端情况;

4. 优化器参数

对于优化器的一些参数,我往往会采取默认值,这是因为,默认值都是论文最初的设置,一般都能够获得不错的表现,我个人一般不做很精细的调试,也不建议这样去做。

超参数调优策略

采用2的幂次方作为 batch_size 的值,并在对数尺度上对学习率进行采样。

1. 网格搜索

  • 定义一个 n 维的网格,每一格都有一个超参数。
  • 对于每个维度,定义可能的取值范围
  • 搜索所有可能的配置并获得最佳结果

我个人一般还是用 Markdown 表格来做记录, 如下:

优化算法 学习率 batch_size
adam 1e-5 128
  • **缺点:**该方法痛点真的很痛,那就是:维数灾难。 随着要精调的超参数的增加,搜索在时间复杂度上也会增加的越多(指数级别),最终使得该策略不可行。
  • 优点: 如果采用较大的搜索范围以及较小步长,该方法有很大概率能找到全局最优值

因此, 我一般尽可能少的去调节次要超参数,比如优化算法默认 Adam 等。此外, 先进行粗调来寻找全局最优值可能的位置,然后采用精调的策略寻找更精确的最优值。

一般只有超参数在 4 个以内才使用网格搜索,不然太费时间了。

2. 随机搜索

随机搜索在搜索范围内随机选取样本点,它认为如果样本点集足够大,那么通过随机采样也能大概率的找到全局最优值或其近似值。

  • 优点: 比网格搜索要快
  • 缺点:结果无法保证,很依靠调参经验。

我一般都是以推荐超参数设置方案来作为第一次的设置,然后围绕这个设置点上下浮动。

3. 贝叶斯优化

网格搜索与随机搜索都是独立于之前的训练的,

https://zhuanlan.zhihu.com/p/29779000

贝叶斯则是利用历史的搜索结果进行优化搜索。其主要有四部分组成,

  • 目标函数,大部分情况下就是模型验证集上的损失。
  • 搜索空间,即各类待搜索的超参数。
  • 优化策略,建立的概率模型和选择超参数的方式。
  • 历史的搜索结果。

首先对搜索空间进行一个先验性的假设猜想,即假设一种选择超参的方式,然后不断的优化更新概率模型,最终的目标是找到验证集上误差最小的一组超参数。

QA

1. 为何学习率那么重要?

当模型训练到一定程度后, 损失将不再减少,这个时候模型的一阶梯度接近于0,此时的Hessian 矩阵通常是两种情况:

  • 正定,即所有特征值均为正,此时通常可以得到一个局部极小值,若这个局部极小值接近全局最小则模型已经能得到不错 的性能了,但若差距很大,则模型性能还有待于提升,通常情况下后者在训练初最常见。
  • 特征值有正有负,此时模型很可能陷入了鞍点,若陷入鞍点,模型性能表现就很差。

2. 卷积核尺寸为何都是奇数?

  • 保证像素点中心位置,避免位置信息偏移
  • 填充边缘时能保证两边都能填充,原矩阵依然对称

3. 深层网络为何难以训练

  • 梯度消失, 梯度爆炸问题

4. 神经网络为何要做深?

  • 神经元数量相同的情况下,深层网络比浅层网络具有更大容量和表达空间。
  • 隐藏层增加意味着由激活函数带来的非线性变换的嵌套层数更多,就能构造更复杂的映射关系。

5. 调节 batch_size 对训练效果影响如何?

  • Batch_size 太小,模型表现效果极其糟糕(error )

6. 合理增加 batch size 有何好处?

  • 内存
  • 利用率提高了,大矩阵乘法的并行化效率提高。
  • 跑完一次 epoch 所需的迭代次数减少,对于相同数据量的处理速度进一步加快。
  • 在一定范围内,一般来说 Batch_Size 越大,其确定的下降方向越准,引起训练震荡越小。

7. 盲目增大 Batch_Size 有何坏处?

  • 内存,显存容量可能撑不住
  • 跑完一次 epoch 所需的迭代次数减少,要想达到相同的精度,其所花费的时间大大增加了,从而对参数的修正也就显得更加缓慢。
  • Batch_Size 增大到一定程度,其确定的下降方向已经基本不再变化。

迁移学习

Reference

一文看懂自然语言处理中迁移学习的现状